Skip to content

Commit 8d68493

Browse files
Merge commit '4b7ecb914f1d7425c010f1c684a0281e32da6f21' as 'src/simplicity'
2 parents aa8310c + 4b7ecb9 commit 8d68493

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+35603
-0
lines changed

src/simplicity/Makefile

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
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
2+
TEST_OBJS := test.o hashBlock.o schnorr0.o schnorr6.o primitive/elements/checkSigHashAllTx1.o
3+
4+
# From https://fastcompression.blogspot.com/2019/01/compiler-warnings.html
5+
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
6+
7+
ifneq ($(doCheck), 1)
8+
CPPFLAGS := $(CPPFLAGS) -DNDEBUG
9+
endif
10+
11+
ifneq ($(strip $(SINGLE_THREADED)),)
12+
# SINGLE_THREADED is non-empty
13+
CPPFLAGS := $(CPPFLAGS) -DSINGLE_THREADED
14+
endif
15+
16+
CFLAGS := -I include
17+
18+
ifeq ($(strip $(SINGLE_THREADED)),)
19+
# SINGLE_THREADED is empty
20+
LDFLAGS := -pthread
21+
endif
22+
23+
# libsecp256k1 is full of conversion warnings, so we compile jets-secp256k1.c separately.
24+
jets-secp256k1.o: jets-secp256k1.c
25+
$(CC) -c $(CFLAGS) $(CWARN) -Wno-conversion $(CPPFLAGS) -o $@ $<
26+
27+
primitive/elements/jets.o: primitive/elements/jets.c
28+
$(CC) -c $(CFLAGS) $(CWARN) -Wno-switch-enum -Wswitch $(CPPFLAGS) -o $@ $<
29+
30+
%.o: %.c
31+
$(CC) -c $(CFLAGS) $(CWARN) $(CPPFLAGS) -o $@ $<
32+
33+
libElementsSimplicity.a: $(OBJS)
34+
ar rcs $@ $^
35+
36+
test: $(TEST_OBJS) libElementsSimplicity.a
37+
$(CC) $^ -o $@ $(LDFLAGS)
38+
39+
install: libElementsSimplicity.a
40+
mkdir -p $(out)/lib
41+
cp $^ $(out)/lib/
42+
cp -R include $(out)/include
43+
44+
check: test
45+
./test
46+
47+
clean:
48+
-rm -f test libElementsSimplicity.a $(TEST_OBJS) $(OBJS)
49+
50+
.PHONY: install check clean

src/simplicity/ascii.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
_Static_assert(
2+
0x20 == ' ' && 0x40 == '@' && 0x60 == '`' &&
3+
0x21 == '!' && 0x41 == 'A' && 0x61 == 'a' &&
4+
0x22 == '"' && 0x42 == 'B' && 0x62 == 'b' &&
5+
0x23 == '#' && 0x43 == 'C' && 0x63 == 'c' &&
6+
0x24 == '$' && 0x44 == 'D' && 0x64 == 'd' &&
7+
0x25 == '%' && 0x45 == 'E' && 0x65 == 'e' &&
8+
0x26 == '&' && 0x46 == 'F' && 0x66 == 'f' &&
9+
0x27 == '\'' && 0x47 == 'G' && 0x67 == 'g' &&
10+
0x28 == '(' && 0x48 == 'H' && 0x68 == 'h' &&
11+
0x29 == ')' && 0x49 == 'I' && 0x69 == 'i' &&
12+
0x2a == '*' && 0x4a == 'J' && 0x6a == 'j' &&
13+
0x2b == '+' && 0x4b == 'K' && 0x6b == 'k' &&
14+
0x2c == ',' && 0x4c == 'L' && 0x6c == 'l' &&
15+
0x2d == '-' && 0x4d == 'M' && 0x6d == 'm' &&
16+
0x2e == '.' && 0x4e == 'N' && 0x6e == 'n' &&
17+
0x2f == '/' && 0x4f == 'O' && 0x6f == 'o' &&
18+
0x30 == '0' && 0x50 == 'P' && 0x70 == 'p' &&
19+
0x31 == '1' && 0x51 == 'Q' && 0x71 == 'q' &&
20+
0x32 == '2' && 0x52 == 'R' && 0x72 == 'r' &&
21+
0x33 == '3' && 0x53 == 'S' && 0x73 == 's' &&
22+
0x34 == '4' && 0x54 == 'T' && 0x74 == 't' &&
23+
0x35 == '5' && 0x55 == 'U' && 0x75 == 'u' &&
24+
0x36 == '6' && 0x56 == 'V' && 0x76 == 'v' &&
25+
0x37 == '7' && 0x57 == 'W' && 0x77 == 'w' &&
26+
0x38 == '8' && 0x58 == 'X' && 0x78 == 'x' &&
27+
0x39 == '9' && 0x59 == 'Y' && 0x79 == 'y' &&
28+
0x3a == ':' && 0x5a == 'Z' && 0x7a == 'z' &&
29+
0x3b == ';' && 0x5b == '[' && 0x7b == '{' &&
30+
0x3c == '<' && 0x5c == '\\' && 0x7c == '|' &&
31+
0x3d == '=' && 0x5d == ']' && 0x7d == '}' &&
32+
0x3e == '>' && 0x5e == '^' && 0x7e == '~' &&
33+
0x3f == '?' && 0x5f == '_'
34+
, "ASCII character set required");

src/simplicity/bitstream.c

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#include "bitstream.h"
2+
3+
#include <assert.h>
4+
#include <limits.h>
5+
#include <stdlib.h>
6+
7+
/* Closes a bitstream by consuming all remaining bits.
8+
* Returns false if CHAR_BIT or more bits remain in the stream or if any remaining bits are non-zero.
9+
*
10+
* Precondition: NULL != stream
11+
*/
12+
bool closeBitstream(bitstream* stream) {
13+
if (1 < stream->len) return false; /* If there is more than one byte remaining. */
14+
if (1 == stream->len && /* If there is one byte remaining */
15+
(0 == stream->offset || /* and either no bits have been consumed */
16+
0 != (*stream->arr & (UCHAR_MAX >> stream->offset)) /* or any of the unconsumed bits are non-zero */
17+
)) return false;
18+
/* Otherwise there are either 0 bits remaining or there are between 1 and CHAR_BITS-1 bits remaining and they are all zero. */
19+
*stream = (bitstream){0};
20+
return true;
21+
}
22+
23+
/* Fetches up to 31 bits from 'stream' as the 'n' least significant bits of return value.
24+
* The 'n' bits are set from the MSB to the LSB.
25+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available.
26+
*
27+
* Precondition: 0 <= n < 32
28+
* NULL != stream
29+
*/
30+
int32_t readNBits(int n, bitstream* stream) {
31+
assert(0 <= n && n < 32);
32+
33+
uint32_t result = 0;
34+
while (CHAR_BIT <= stream->offset + n) {
35+
if (!stream->len) return SIMPLICITY_ERR_BITSTREAM_EOF;
36+
n -= CHAR_BIT - stream->offset;
37+
result |= (uint32_t)(*stream->arr & (UCHAR_MAX >> stream->offset)) << n;
38+
stream->arr++; stream->len--; stream->offset = 0;
39+
}
40+
/* stream->offset + n < CHAR_BIT */
41+
if (n) {
42+
if (!stream->len) return SIMPLICITY_ERR_BITSTREAM_EOF;
43+
stream->offset += (unsigned char)n;
44+
result |= (*stream->arr >> (CHAR_BIT - stream->offset)) & ((UCHAR_MAX >> (CHAR_BIT - n)));
45+
}
46+
return (int32_t)result;
47+
}
48+
/* Decode an encoded bitstring up to length 1.
49+
* If successful returns the length of the bitstring and 'result' contains the decoded bits.
50+
* The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded.
51+
* Any remaining bits in 'result' are reset to 0.
52+
* If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified).
53+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified).
54+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified).
55+
*
56+
* Precondition: NULL != result
57+
* NULL != stream
58+
*/
59+
static int32_t decodeUpto1Bit(int32_t* result, bitstream* stream) {
60+
*result = read1Bit(stream);
61+
if (*result <= 0) return *result;
62+
63+
*result = read1Bit(stream);
64+
if (*result < 0) return *result;
65+
if (0 != *result) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE;
66+
67+
*result = read1Bit(stream);
68+
if (*result < 0) return *result;
69+
return 1;
70+
}
71+
72+
/* Decode an encoded number between 1 and 3 inclusive.
73+
* When successful returns the decoded result.
74+
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned.
75+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned.
76+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned.
77+
*
78+
* Precondition: NULL != stream
79+
*/
80+
static int32_t decodeUpto3(bitstream* stream) {
81+
int32_t result;
82+
int32_t len = decodeUpto1Bit(&result, stream);
83+
if (len < 0) return len;
84+
result |= 1 << len;
85+
return result;
86+
}
87+
88+
/* Decode an encoded bitstring up to length 3.
89+
* If successful returns the length of the bitstring and 'result' contains the decoded bits.
90+
* The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded.
91+
* Any remaining bits in 'result' are reset to 0.
92+
* If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified).
93+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified).
94+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified).
95+
*
96+
* Precondition: NULL != result
97+
* NULL != stream
98+
*/
99+
static int32_t decodeUpto3Bits(int32_t* result, bitstream* stream) {
100+
int32_t bit = read1Bit(stream);
101+
if (bit < 0) return bit;
102+
103+
*result = 0;
104+
if (0 == bit) {
105+
return 0;
106+
} else {
107+
int32_t n = decodeUpto3(stream);
108+
if (0 <= n) {
109+
*result = readNBits(n, stream);
110+
if (*result < 0) return *result;
111+
}
112+
return n;
113+
}
114+
}
115+
116+
/* Decode an encoded number between 1 and 15 inclusive.
117+
* When successful returns the decoded result.
118+
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned.
119+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned.
120+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned.
121+
*
122+
* Precondition: NULL != stream
123+
*/
124+
static int32_t decodeUpto15(bitstream* stream) {
125+
int32_t result;
126+
int32_t len = decodeUpto3Bits(&result, stream);
127+
if (len < 0) return len;
128+
result |= 1 << len;
129+
return result;
130+
}
131+
132+
/* Decode an encoded bitstring up to length 15.
133+
* If successful returns the length of the bitstring and 'result' contains the decoded bits.
134+
* The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded.
135+
* Any remaining bits in 'result' are reset to 0.
136+
* If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified).
137+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified).
138+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified).
139+
*
140+
* Precondition: NULL != result
141+
* NULL != stream
142+
*/
143+
static int32_t decodeUpto15Bits(int32_t* result, bitstream* stream) {
144+
int32_t bit = read1Bit(stream);
145+
if (bit < 0) return bit;
146+
147+
*result = 0;
148+
if (0 == bit) {
149+
return 0;
150+
} else {
151+
int32_t n = decodeUpto15(stream);
152+
if (0 <= n) {
153+
*result = readNBits(n, stream);
154+
if (*result < 0) return *result;
155+
}
156+
return n;
157+
}
158+
}
159+
160+
/* Decode an encoded number between 1 and 65535 inclusive.
161+
* When successful returns the decoded result.
162+
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned.
163+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned.
164+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned.
165+
*
166+
* Precondition: NULL != stream
167+
*/
168+
static int32_t decodeUpto65535(bitstream* stream) {
169+
int32_t result;
170+
int32_t len = decodeUpto15Bits(&result, stream);
171+
if (len < 0) return len;
172+
result |= 1 << len;
173+
return result;
174+
}
175+
176+
/* Decode an encoded number between 1 and 2^31 - 1 inclusive.
177+
* When successful returns the decoded result.
178+
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned.
179+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned.
180+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned.
181+
*
182+
* Precondition: NULL != stream
183+
*/
184+
int32_t decodeUptoMaxInt(bitstream* stream) {
185+
int32_t bit = read1Bit(stream);
186+
if (bit < 0) return bit;
187+
if (0 == bit) {
188+
return 1;
189+
} else {
190+
int32_t n = decodeUpto65535(stream);
191+
if (n < 0) return n;
192+
if (30 < n) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE;
193+
{
194+
int32_t result = readNBits(n, stream);
195+
if (result < 0) return result;
196+
return ((1 << n) | result);
197+
}
198+
}
199+
}
200+
201+
/* Fills a 'bitstring' containing 'n' bits from 'stream'.
202+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available.
203+
* If successful, '*result' is set to a bitstring with 'n' bits read from 'stream' and 0 is returned.
204+
*
205+
* If an error is returned '*result' might be modified.
206+
*
207+
* Precondition: NULL != result
208+
* n <= 2^31
209+
* NULL != stream
210+
*/
211+
int32_t readBitstring(bitstring* result, size_t n, bitstream* stream) {
212+
static_assert(0x8000u + 2*(CHAR_BIT - 1) <= SIZE_MAX, "size_t needs to be at least 32-bits");
213+
assert(n <= 0x8000u);
214+
size_t total_offset = n + stream->offset;
215+
/* |= stream->len * CHAR_BIT < total_offset iff stream->len < (total_offset + (CHAR_BIT - 1)) / CHAR_BIT */
216+
if (stream->len < (total_offset + (CHAR_BIT - 1)) / CHAR_BIT) return SIMPLICITY_ERR_BITSTREAM_EOF;
217+
/* total_offset <= stream->len * CHAR_BIT */
218+
*result = (bitstring)
219+
{ .arr = stream->arr
220+
, .offset = stream->offset
221+
, .len = n
222+
};
223+
{
224+
size_t delta = total_offset / CHAR_BIT;
225+
stream->arr += delta; stream->len -= delta;
226+
stream->offset = total_offset % CHAR_BIT;
227+
/* Note that if 0 == stream->len then 0 == stream->offset. */
228+
}
229+
return 0;
230+
}

src/simplicity/bitstream.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* This module provides functions for initializing and reading from a stream of bits from a 'FILE'. */
2+
#ifndef SIMPLICITY_BITSTREAM_H
3+
#define SIMPLICITY_BITSTREAM_H
4+
5+
#include <stdio.h>
6+
#include <stdint.h>
7+
#include <stdbool.h>
8+
#include "bitstring.h"
9+
#include "errorCodes.h"
10+
11+
/* :TODO: consider adding an 'invalid' state that can be set when parsing has failed and should not be resumed. */
12+
/* Datatype representing a bit stream.
13+
* Bits are streamed from MSB to LSB.
14+
*
15+
* Invariant: unsigned char arr[len]
16+
* 0 <= offset < CHAR_BIT
17+
* 0 == len implies 0 == offset
18+
*/
19+
typedef struct bitstream {
20+
const unsigned char *arr; /* Underlying byte array */
21+
size_t len; /* Length of arr (in bytes) */
22+
unsigned char offset; /* Number of bits parsed from the beginning of arr */
23+
} bitstream;
24+
25+
/* Initialize a bit stream, 'stream', from a given byte array.
26+
* Precondition: unsigned char arr[len];
27+
*/
28+
static inline bitstream initializeBitstream(const unsigned char* arr, size_t len) {
29+
return (bitstream){ .arr = arr, .len = len };
30+
}
31+
32+
/* Closes a bitstream by consuming all remaining bits.
33+
* Returns false if CHAR_BIT or more bits remain in the stream or if any remaining bits are non-zero.
34+
*
35+
* Precondition: NULL != stream
36+
*/
37+
bool closeBitstream(bitstream* stream);
38+
39+
/* Fetches up to 31 bits from 'stream' as the 'n' least significant bits of return value.
40+
* The 'n' bits are set from the MSB to the LSB.
41+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available.
42+
*
43+
* Precondition: 0 <= n < 32
44+
* NULL != stream
45+
*/
46+
int32_t readNBits(int n, bitstream* stream);
47+
48+
/* Returns one bit from 'stream', 0 or 1.
49+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if no bits are available.
50+
*
51+
* Precondition: NULL != stream
52+
*/
53+
static inline int32_t read1Bit(bitstream* stream) {
54+
return readNBits(1, stream);
55+
}
56+
57+
/* Decode an encoded number between 1 and 2^31 - 1 inclusive.
58+
* When successful returns the decoded result.
59+
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned.
60+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned.
61+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned.
62+
*
63+
* Precondition: NULL != stream
64+
*/
65+
int32_t decodeUptoMaxInt(bitstream* stream);
66+
67+
/* Fills a 'bitstring' containing 'n' bits from 'stream'.
68+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available.
69+
* If successful, '*result' is set to a bitstring with 'n' bits read from 'stream' and 0 is returned.
70+
*
71+
* If an error is returned '*result' might be modified.
72+
*
73+
* Precondition: NULL != result
74+
* n <= 2^31
75+
* NULL != stream
76+
*/
77+
int32_t readBitstring(bitstring* result, size_t n, bitstream* stream);
78+
#endif

0 commit comments

Comments
 (0)