Skip to content

Commit db0f762

Browse files
committed
Export de/encoding during fuzzing only
- make decode and encode modules private by default - move BitWriter to own public module
1 parent 6b6cec1 commit db0f762

File tree

15 files changed

+165
-138
lines changed

15 files changed

+165
-138
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ jobs:
9999
FEATURES: honggfuzz_fuzz
100100
run: |
101101
cd fuzz/
102-
for f in $FEATURES; do echo "Features: $f" && cargo test --no-default-features --features="$f"; done
103-
echo "No default features" && cargo test --no-default-features
104-
echo "All features" && cargo test --all-features
102+
for f in $FEATURES; do echo "Features: $f" && RUSTFLAGS=--cfg=fuzzing cargo test --no-default-features --features="$f"; done
103+
echo "No default features" && RUSTFLAGS=--cfg=fuzzing cargo test --no-default-features
104+
echo "All features" && RUSTFLAGS=--cfg=fuzzing cargo test --all-features
105105
- name: Running fuzz tests
106106
env:
107107
FEATURES: honggfuzz_fuzz

fuzz/fuzz_targets/rtt_natural.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
extern crate simplicity;
1616

1717
use simplicity::bititer::BitIter;
18-
use simplicity::encode::BitWriter;
18+
use simplicity::bitwriter::BitWriter;
1919
use simplicity::{decode, encode};
2020

2121
fn do_test(data: &[u8]) {
@@ -85,6 +85,9 @@ mod tests {
8585

8686
#[test]
8787
fn duplicate_crash() {
88+
#[cfg(not(fuzzing))]
89+
compile_error!("To build this target or run the unit tests you must set RUSTFLAGS=--cfg=fuzzing");
90+
8891
let mut a = Vec::new();
8992
extend_vec_from_hex("00", &mut a);
9093
super::do_test(&a);

src/bitwriter.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Rust Simplicity Library
2+
// Written in 2020 by
3+
// Andrew Poelstra <[email protected]>
4+
//
5+
// To the extent possible under law, the author(s) have dedicated all
6+
// copyright and related and neighboring rights to this software to
7+
// the public domain worldwide. This software is distributed without
8+
// any warranty.
9+
//
10+
// You should have received a copy of the CC0 Public Domain Dedication
11+
// along with this software.
12+
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13+
//
14+
15+
use std::io;
16+
17+
/// Bitwise writer formed by wrapping a bytewise [`io::Write`].
18+
/// Bits are written in big-endian order.
19+
/// Bytes are filled with zeroes for padding.
20+
pub struct BitWriter<W: io::Write> {
21+
/// Byte writer
22+
w: W,
23+
/// Current byte that contains current bits, yet to be written out
24+
cache: u8,
25+
/// Number of current bits
26+
cache_len: usize,
27+
/// Total number of written bits
28+
total_written: usize,
29+
}
30+
31+
impl<W: io::Write> From<W> for BitWriter<W> {
32+
fn from(w: W) -> Self {
33+
BitWriter {
34+
w,
35+
cache: 0,
36+
cache_len: 0,
37+
total_written: 0,
38+
}
39+
}
40+
}
41+
42+
impl<W: io::Write> io::Write for BitWriter<W> {
43+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
44+
self.w.write(buf)
45+
}
46+
47+
/// Does **not** write out cached bits
48+
/// (i.e. bits written since the last byte boundary).
49+
/// To do this you must call [`BitWriter::flush_all()`].
50+
fn flush(&mut self) -> io::Result<()> {
51+
self.w.flush()
52+
}
53+
}
54+
55+
impl<W: io::Write> BitWriter<W> {
56+
/// Create a bitwise writer from a bytewise one.
57+
/// Equivalent to using [`From`].
58+
pub fn new(w: W) -> BitWriter<W> {
59+
BitWriter::from(w)
60+
}
61+
62+
/// Write a single bit.
63+
pub fn write_bit(&mut self, b: bool) -> io::Result<()> {
64+
if self.cache_len < 8 {
65+
self.cache_len += 1;
66+
self.total_written += 1;
67+
if b {
68+
self.cache |= 1 << (8 - self.cache_len);
69+
}
70+
Ok(())
71+
} else {
72+
self.w.write_all(&[self.cache])?;
73+
self.cache_len = 0;
74+
self.cache = 0;
75+
self.write_bit(b)
76+
}
77+
}
78+
79+
/// Write out all cached bits.
80+
/// This may write up to two bytes and flushes the underlying [`io::Write`].
81+
pub fn flush_all(&mut self) -> io::Result<()> {
82+
self.w.write_all(&[self.cache])?;
83+
self.cache_len = 0;
84+
self.cache = 0;
85+
86+
io::Write::flush(&mut self.w)
87+
}
88+
89+
/// Return total number of written bits.
90+
pub fn n_total_written(&self) -> usize {
91+
self.total_written
92+
}
93+
94+
/// Write up to 64 bits in big-endian order.
95+
/// The first `len` many _least significant_ bits from `n` are written.
96+
///
97+
/// Returns the number of written bits.
98+
pub fn write_bits_be(&mut self, n: u64, len: usize) -> io::Result<usize> {
99+
for i in 0..len {
100+
self.write_bit(n & (1 << (len - i - 1)) != 0)?;
101+
}
102+
Ok(len)
103+
}
104+
}

src/core/commit.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@
1414
//
1515

1616
use crate::bititer::BitIter;
17-
use crate::core::iter::DagIterable;
17+
use crate::bitwriter::BitWriter;
18+
use crate::core::iter::{DagIterable, WitnessIterator};
1819
use crate::core::node::NodeInner;
1920
use crate::core::{Node, Value};
20-
use crate::decode::WitnessIterator;
21-
use crate::encode::BitWriter;
2221
use crate::jet::{Application, JetNode};
2322
use crate::merkle::cmr::Cmr;
2423
use crate::merkle::{cmr, imr};

src/core/iter.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
//! Iterators over DAGs
1616
1717
use crate::core::node::{NodeInner, RefWrapper};
18+
use crate::core::types::Type;
19+
use crate::core::Value;
1820
use crate::jet::Application;
21+
use crate::Error;
1922
use std::collections::HashSet;
2023
use std::hash::Hash;
2124

@@ -157,3 +160,22 @@ where
157160
}
158161
})
159162
}
163+
164+
/// Iterator over witness values that asks for the value type on each iteration.
165+
pub trait WitnessIterator {
166+
/// Return the next witness value of the given type.
167+
fn next(&mut self, ty: &Type) -> Result<Value, Error>;
168+
169+
/// Consume the iterator and check the total witness length.
170+
fn finish(self) -> Result<(), Error>;
171+
}
172+
173+
impl<I: Iterator<Item = Value>> WitnessIterator for I {
174+
fn next(&mut self, _ty: &Type) -> Result<Value, Error> {
175+
Iterator::next(self).ok_or(Error::EndOfStream)
176+
}
177+
178+
fn finish(self) -> Result<(), Error> {
179+
Ok(())
180+
}
181+
}

src/core/node.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
//
1414

1515
use crate::bititer::BitIter;
16+
use crate::bitwriter::BitWriter;
1617
use crate::core::iter::DagIterable;
1718
use crate::core::types::Type;
1819
use crate::core::{iter, Value};
1920
use crate::decode::WitnessDecoder;
20-
use crate::encode::BitWriter;
2121
use crate::jet::{Application, JetNode};
2222
use crate::merkle::cmr::Cmr;
2323
use crate::merkle::imr::Imr;

src/decode.rs

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
2020
use crate::bititer::BitIter;
2121
use crate::core::commit::{CommitNodeInner, RefWrapper};
22-
use crate::core::iter::DagIterable;
22+
use crate::core::iter::{DagIterable, WitnessIterator};
2323
use crate::core::types::{Type, TypeInner};
2424
use crate::core::{CommitNode, Value};
2525
use crate::jet::Application;
@@ -31,7 +31,7 @@ use std::rc::Rc;
3131
/// Decode a Simplicity program from bits where witness data follows.
3232
///
3333
/// The number of decoded witness nodes corresponds exactly to the witness data.
34-
pub(crate) fn decode_program_exact_witness<I: Iterator<Item = u8>, App: Application>(
34+
pub fn decode_program_exact_witness<I: Iterator<Item = u8>, App: Application>(
3535
bits: &mut BitIter<I>,
3636
) -> Result<Rc<CommitNode<(), App>>, Error> {
3737
decode_program(bits, false)
@@ -41,7 +41,7 @@ pub(crate) fn decode_program_exact_witness<I: Iterator<Item = u8>, App: Applicat
4141
///
4242
/// Witness nodes are made fresh, i.e., each witness node has at most one parent.
4343
/// This increases the number of witness nodes and hence the length of the required witness data.
44-
pub(crate) fn decode_program_fresh_witness<I: Iterator<Item = u8>, App: Application>(
44+
pub fn decode_program_fresh_witness<I: Iterator<Item = u8>, App: Application>(
4545
bits: &mut BitIter<I>,
4646
) -> Result<Rc<CommitNode<(), App>>, Error> {
4747
decode_program(bits, true)
@@ -225,25 +225,6 @@ fn get_child_from_index<App: Application>(
225225
}
226226
}
227227

228-
/// Iterator over witness values that asks for the value type on each iteration.
229-
pub trait WitnessIterator {
230-
/// Return the next witness value of the given type.
231-
fn next(&mut self, ty: &Type) -> Result<Value, Error>;
232-
233-
/// Consume the iterator and check the total witness length.
234-
fn finish(self) -> Result<(), Error>;
235-
}
236-
237-
impl<I: Iterator<Item = Value>> WitnessIterator for I {
238-
fn next(&mut self, _ty: &Type) -> Result<Value, Error> {
239-
Iterator::next(self).ok_or(Error::EndOfStream)
240-
}
241-
242-
fn finish(self) -> Result<(), Error> {
243-
Ok(())
244-
}
245-
}
246-
247228
/// Implementation of [`WitnessIterator`] for an underlying [`BitIter`].
248229
#[derive(Debug)]
249230
pub struct WitnessDecoder<'a, I: Iterator<Item = u8>> {
@@ -253,7 +234,10 @@ pub struct WitnessDecoder<'a, I: Iterator<Item = u8>> {
253234

254235
impl<'a, I: Iterator<Item = u8>> WitnessDecoder<'a, I> {
255236
/// Create a new witness decoder for the given bit iterator.
256-
/// To work, this method must be used **after** [`decode_program_no_witness()`]!
237+
///
238+
/// # Usage
239+
///
240+
/// This method must be used **after** the program serialization has been read by the iterator.
257241
pub fn new(bits: &'a mut BitIter<I>) -> Result<Self, Error> {
258242
let bit_len = match bits.next() {
259243
Some(false) => 0,
@@ -302,7 +286,7 @@ pub fn decode_value<I: Iterator<Item = bool>>(ty: &Type, iter: &mut I) -> Result
302286
}
303287

304288
/// Decode a 256-bit hash from bits.
305-
fn decode_hash<I: Iterator<Item = u8>>(iter: &mut BitIter<I>) -> Result<[u8; 32], Error> {
289+
pub fn decode_hash<I: Iterator<Item = u8>>(iter: &mut BitIter<I>) -> Result<[u8; 32], Error> {
306290
let mut h = [0; 32];
307291

308292
for b in &mut h {
@@ -362,8 +346,8 @@ pub fn decode_natural<I: Iterator<Item = bool>>(
362346
#[cfg(test)]
363347
mod tests {
364348
use super::*;
349+
use crate::bitwriter::BitWriter;
365350
use crate::encode;
366-
use crate::encode::BitWriter;
367351

368352
#[test]
369353
fn decode_fixed() {

0 commit comments

Comments
 (0)