Skip to content

Commit

Permalink
Leverage rand_core::RngCore implementations in Rng (#60)
Browse files Browse the repository at this point in the history
* Leverage `rand_core::RngCore` implementations in `Rng`

* Refactor Rng wasm/js binding

* Format code
  • Loading branch information
appcypher authored Sep 12, 2022
1 parent a38daf5 commit deeea03
Show file tree
Hide file tree
Showing 12 changed files with 79 additions and 81 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ xxhash-rust = { version = "0.8.5", features = ["xxh3"] }
lazy_static = "1.4.0"
thiserror = "1.0.31"
aes-gcm = "0.9.4"
rand_core = "0.6.3"

[dev-dependencies]
env_logger = "0.9.0"
test-log = "0.2.10"
rand = "0.8.5"
proptest = "1.0.0"
test-strategy = "0.2.0"

Expand Down
33 changes: 0 additions & 33 deletions crates/fs/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ use crate::{error, FsError};

pub(crate) struct ByteArrayVisitor<const N: usize>;

#[cfg(test)]
pub(crate) struct TestRng();

#[cfg(test)]
pub(crate) struct ProptestRng(proptest::test_runner::TestRng);

//--------------------------------------------------------------------------------------------------
// Implementations
//--------------------------------------------------------------------------------------------------
Expand All @@ -36,33 +30,6 @@ impl<'de, const N: usize> Visitor<'de> for ByteArrayVisitor<N> {
}
}

#[cfg(test)]
impl crate::private::Rng for TestRng {
fn random_bytes<const N: usize>(&mut self) -> [u8; N] {
use rand::RngCore;
let mut bytes = [0u8; N];
rand::thread_rng().fill_bytes(&mut bytes);
bytes
}
}

#[cfg(test)]
impl ProptestRng {
pub(crate) fn from_seed(algorithm: proptest::test_runner::RngAlgorithm, seed: &[u8]) -> Self {
Self(proptest::test_runner::TestRng::from_seed(algorithm, seed))
}
}

#[cfg(test)]
impl crate::private::Rng for ProptestRng {
fn random_bytes<const N: usize>(&mut self) -> [u8; N] {
use rand::RngCore;
let mut bytes = [0u8; N];
self.0.fill_bytes(&mut bytes);
bytes
}
}

//--------------------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------------------
Expand Down
19 changes: 10 additions & 9 deletions crates/fs/private/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,12 +598,13 @@ impl Id for PrivateDirectory {
#[cfg(test)]
mod private_directory_tests {
use super::*;
use crate::{utils::TestRng, MemoryBlockStore, HASH_BYTE_SIZE};
use crate::{MemoryBlockStore, HASH_BYTE_SIZE};
use proptest::test_runner::{RngAlgorithm, TestRng};
use test_log::test;

#[test(async_std::test)]
async fn look_up_can_fetch_file_added_to_directory() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
rng.random_bytes::<HASH_BYTE_SIZE>(),
Expand Down Expand Up @@ -638,7 +639,7 @@ mod private_directory_tests {

#[test(async_std::test)]
async fn look_up_cannot_fetch_file_not_added_to_directory() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
rng.random_bytes::<HASH_BYTE_SIZE>(),
Expand All @@ -658,7 +659,7 @@ mod private_directory_tests {

#[test(async_std::test)]
async fn mkdir_can_create_new_directory() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
rng.random_bytes::<HASH_BYTE_SIZE>(),
Expand Down Expand Up @@ -690,7 +691,7 @@ mod private_directory_tests {

#[test(async_std::test)]
async fn ls_can_list_children_under_directory() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
rng.random_bytes::<HASH_BYTE_SIZE>(),
Expand Down Expand Up @@ -749,7 +750,7 @@ mod private_directory_tests {

#[test(async_std::test)]
async fn rm_can_remove_children_from_directory() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
rng.random_bytes::<HASH_BYTE_SIZE>(),
Expand Down Expand Up @@ -822,7 +823,7 @@ mod private_directory_tests {

#[async_std::test]
async fn read_can_fetch_userland_of_file_added_to_directory() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
rng.random_bytes::<HASH_BYTE_SIZE>(),
Expand Down Expand Up @@ -857,7 +858,7 @@ mod private_directory_tests {
async fn path_nodes_can_generates_new_path_nodes() {
let store = &mut MemoryBlockStore::default();
let hamt = Rc::new(PrivateForest::new());
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);

let path_nodes = PrivateDirectory::create_path_nodes(
&["Documents".into(), "Apps".into()],
Expand Down Expand Up @@ -891,7 +892,7 @@ mod private_directory_tests {
async fn search_latest_finds_the_most_recent() {
let store = &mut MemoryBlockStore::default();
let hamt = Rc::new(PrivateForest::new());
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);

let root_dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
Expand Down
11 changes: 4 additions & 7 deletions crates/fs/private/forest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use log::debug;

use crate::{BlockStore, HashOutput};

use super::{hamt::Hamt, namefilter::Namefilter, Key, PrivateNode, PrivateRef};
use super::{hamt::Hamt, namefilter::Namefilter, Key, PrivateNode, PrivateRef, Rng};

//--------------------------------------------------------------------------------------------------
// Type Definitions
Expand All @@ -16,10 +16,6 @@ use super::{hamt::Hamt, namefilter::Namefilter, Key, PrivateNode, PrivateRef};
// TODO(appcypher): And eventually to BTreeSet<PrivateLink<PrivateNode>>.
pub type PrivateForest = Hamt<Namefilter, Cid>;

pub trait Rng {
fn random_bytes<const N: usize>(&mut self) -> [u8; N];
}

//--------------------------------------------------------------------------------------------------
// Implementations
//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -136,19 +132,20 @@ impl PrivateForest {

#[cfg(test)]
mod hamt_store_tests {
use proptest::test_runner::{RngAlgorithm, TestRng};
use std::rc::Rc;
use test_log::test;

use chrono::Utc;

use super::*;
use crate::{private::PrivateDirectory, utils::TestRng, MemoryBlockStore};
use crate::{private::PrivateDirectory, MemoryBlockStore};

#[test(async_std::test)]
async fn inserted_items_can_be_fetched() {
let store = &mut MemoryBlockStore::new();
let hamt = Rc::new(PrivateForest::new());
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);

let dir = Rc::new(PrivateDirectory::new(
Namefilter::default(),
Expand Down
8 changes: 3 additions & 5 deletions crates/fs/private/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,19 @@ impl Debug for Key {

#[cfg(test)]
mod key_prop_tests {
use crate::utils::ProptestRng;

use super::*;
use proptest::prelude::any;
use proptest::test_runner::RngAlgorithm;
use proptest::test_runner::{RngAlgorithm, TestRng};
use test_strategy::proptest;

#[proptest(cases = 50)]
#[proptest(cases = 100)]
fn key_can_encrypt_and_decrypt_data(
#[strategy(any::<Vec<u8>>())] data: Vec<u8>,
#[strategy(any::<[u8; 32]>())] rng_seed: [u8; 32],
key_bytes: [u8; 32],
) {
let key = Key::new(key_bytes);
let rng = &mut ProptestRng::from_seed(RngAlgorithm::ChaCha, &rng_seed);
let rng = &mut TestRng::from_seed(RngAlgorithm::ChaCha, &rng_seed);

let encrypted = key.encrypt(&Key::generate_nonce(rng), &data).unwrap();
let decrypted = key.decrypt(&encrypted).unwrap();
Expand Down
2 changes: 2 additions & 0 deletions crates/fs/private/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ mod key;
mod link;
pub mod namefilter;
mod node;
mod rng;

pub use directory::*;
pub use file::*;
pub use forest::*;
pub use key::*;
pub use link::*;
pub use node::*;
pub use rng::*;
42 changes: 22 additions & 20 deletions crates/fs/private/namefilter/bloomfilter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,9 @@ impl<'de, const N: usize, const K: usize> Deserialize<'de> for BloomFilter<N, K>
//------------------------------------------------------------------------------

#[cfg(test)]
mod bloomfilter_tests {
use libipld::serde as ipld_serde;
use rand::{thread_rng, Rng};

mod bloomfilter_unit_tests {
use super::*;
use libipld::serde as ipld_serde;

#[test]
fn bloom_filter_can_add_and_validate_item_existence() {
Expand All @@ -187,22 +185,6 @@ mod bloomfilter_tests {
assert!(!bloom.contains(b"tird"));
}

#[test]
fn iterator_can_give_unbounded_number_of_indices() {
let iter = HashIndexIterator::<_, 200>::new(&"hello");

let indices = (0..20)
.map(|_| {
let count = thread_rng().gen_range(0..500);
(iter.clone().take(count).collect::<Vec<_>>(), count)
})
.collect::<Vec<_>>();

for (indices, count) in indices {
assert_eq!(indices.len(), count);
}
}

#[test]
fn serialized_bloom_filter_can_be_deserialized_correctly() {
let mut bloom = BloomFilter::<256, 30>::new();
Expand All @@ -217,3 +199,23 @@ mod bloomfilter_tests {
assert_eq!(deserialized, bloom);
}
}

#[cfg(test)]
mod bloomfilter_prop_tests {
use test_strategy::proptest;

use super::HashIndexIterator;

#[proptest]
fn iterator_can_give_unbounded_number_of_indices(#[strategy(0usize..500)] count: usize) {
let iter = HashIndexIterator::<_, 200>::new(&"hello");

let indices = (0..20)
.map(|_| (iter.clone().take(count).collect::<Vec<_>>(), count))
.collect::<Vec<_>>();

for (indices, count) in indices {
assert_eq!(indices.len(), count);
}
}
}
4 changes: 2 additions & 2 deletions crates/fs/private/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,13 @@ impl PrivateNodeHeader {

#[cfg(test)]
mod private_node_tests {
use crate::{private::Rng, utils::TestRng};
use proptest::test_runner::{RngAlgorithm, TestRng};

use super::*;

#[test]
fn serialized_private_node_can_be_deserialized() {
let rng = &mut TestRng();
let rng = &mut TestRng::deterministic_rng(RngAlgorithm::ChaCha);
let original_file = PrivateNode::File(Rc::new(PrivateFile::new(
Namefilter::default(),
rng.random_bytes::<32>(),
Expand Down
12 changes: 12 additions & 0 deletions crates/fs/private/rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use rand_core::RngCore;

pub trait Rng: RngCore {
fn random_bytes<const N: usize>(&mut self) -> [u8; N] {
let mut bytes = [0u8; N];
self.fill_bytes(&mut bytes);
bytes
}
}

#[cfg(test)]
impl crate::private::Rng for proptest::test_runner::TestRng {}
1 change: 1 addition & 0 deletions crates/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ async-trait = "0.1"
console_error_panic_hook = { version = "0.1", optional = true }
wee_alloc = { version = "0.4", optional = true }
cfg-if = "1.0.0"
rand_core = "0.6.3"

[dev-dependencies]
wasm-bindgen-test = "0.3"
Expand Down
23 changes: 20 additions & 3 deletions crates/wasm/fs/private/rng.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rand_core::RngCore;
use wasm_bindgen::prelude::wasm_bindgen;
use wnfs::private::Rng as WnfsRng;

Expand All @@ -18,8 +19,24 @@ extern "C" {
// Implementations
//--------------------------------------------------------------------------------------------------

impl WnfsRng for Rng {
fn random_bytes<const N: usize>(&mut self) -> [u8; N] {
self.get_random_bytes(N).try_into().unwrap()
impl RngCore for Rng {
fn next_u32(&mut self) -> u32 {
let bytes = self.get_random_bytes(4);
u32::from_le_bytes(bytes.try_into().unwrap())
}

fn next_u64(&mut self) -> u64 {
let bytes = self.get_random_bytes(8);
u64::from_le_bytes(bytes.try_into().unwrap())
}

fn fill_bytes(&mut self, dest: &mut [u8]) {
dest.copy_from_slice(&self.get_random_bytes(dest.len()));
}

fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
Ok(self.fill_bytes(dest))
}
}

impl WnfsRng for Rng {}

0 comments on commit deeea03

Please sign in to comment.