Skip to content

Commit f502c24

Browse files
Squashed 'src/simplicity/' content from commit 86ac0f92c4
git-subtree-dir: src/simplicity git-subtree-split: 86ac0f92c4b2b6d694dca85dce3b6909aed25894
0 parents  commit f502c24

Some content is hidden

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

103 files changed

+52253
-0
lines changed

Makefile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
OBJS := bitstream.o cmr.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/elementsJets.o primitive/elements/primitive.o
2+
TEST_OBJS := test.o ctx8Pruned.o ctx8Unpruned.o hashBlock.o regression4.o schnorr0.o schnorr6.o typeSkipTest.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) -DPRODUCTION
9+
endif
10+
11+
CFLAGS := $(CFLAGS) -I include
12+
13+
# libsecp256k1 is full of conversion warnings, so we compile jets-secp256k1.c separately.
14+
jets-secp256k1.o: jets-secp256k1.c
15+
$(CC) -c $(CFLAGS) $(CWARN) -Wno-conversion $(CPPFLAGS) -o $@ $<
16+
17+
primitive/elements/elementsJets.o: primitive/elements/elementsJets.c
18+
$(CC) -c $(CFLAGS) $(CWARN) -Wno-switch-enum -Wswitch $(CPPFLAGS) -o $@ $<
19+
20+
sha256.o: sha256.c
21+
$(CC) -c $(CFLAGS) -msha -msse4 $(CWARN) -Wno-cast-align -Wno-sign-conversion $(CPPFLAGS) -o $@ $<
22+
23+
%.o: %.c
24+
$(CC) -c $(CFLAGS) $(CWARN) $(CPPFLAGS) -o $@ $<
25+
26+
libElementsSimplicity.a: $(OBJS)
27+
ar rcs $@ $^
28+
29+
test: $(TEST_OBJS) libElementsSimplicity.a
30+
$(CC) $^ -o $@ $(LDFLAGS)
31+
32+
install: libElementsSimplicity.a
33+
mkdir -p $(out)/lib
34+
cp $^ $(out)/lib/
35+
cp -R include $(out)/include
36+
37+
check: test
38+
./test
39+
40+
clean:
41+
-rm -f test libElementsSimplicity.a $(TEST_OBJS) $(OBJS)
42+
43+
.PHONY: install check clean

bitstream.c

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

bitstream.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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 <stddef.h>
6+
#include <stdint.h>
7+
#include <stdbool.h>
8+
#include <simplicity/errorCodes.h>
9+
#include "bitstring.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 'SIMPLICITY_ERR_BITSTREAM_TRAILING_BYTES' if CHAR_BIT or more bits remain in the stream.
34+
* Otherwise, returns 'SIMPLICITY_ERR_BITSTREAM_ILLEGAL_PADDING' if any remaining bits are non-zero.
35+
* Otherwise returns 'SIMPLICITY_NO_ERROR'.
36+
*
37+
* Precondition: NULL != stream
38+
*/
39+
simplicity_err simplicity_closeBitstream(bitstream* stream);
40+
41+
/* Fetches up to 31 bits from 'stream' as the 'n' least significant bits of return value.
42+
* The 'n' bits are set from the MSB to the LSB.
43+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available.
44+
*
45+
* Precondition: 0 <= n < 32
46+
* NULL != stream
47+
*/
48+
int32_t simplicity_readNBits(int n, bitstream* stream);
49+
50+
/* Returns one bit from 'stream', 0 or 1.
51+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if no bits are available.
52+
*
53+
* Precondition: NULL != stream
54+
*/
55+
static inline int32_t read1Bit(bitstream* stream) {
56+
return simplicity_readNBits(1, stream);
57+
}
58+
59+
/* Decode an encoded number between 1 and 2^31 - 1 inclusive.
60+
* When successful returns the decoded result.
61+
* If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned.
62+
* If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned.
63+
* If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned.
64+
*
65+
* Precondition: NULL != stream
66+
*/
67+
int32_t simplicity_decodeUptoMaxInt(bitstream* stream);
68+
69+
/* Fills a 'bitstring' containing 'n' bits from 'stream'.
70+
* Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available.
71+
* If successful, '*result' is set to a bitstring with 'n' bits read from 'stream' and 'SIMPLICITY_NO_ERROR' is returned.
72+
*
73+
* If an error is returned '*result' might be modified.
74+
*
75+
* Precondition: NULL != result
76+
* n <= 2^31
77+
* NULL != stream
78+
*/
79+
simplicity_err simplicity_readBitstring(bitstring* result, size_t n, bitstream* stream);
80+
#endif

0 commit comments

Comments
 (0)