Skip to content

Commit

Permalink
Make structures Send (#28)
Browse files Browse the repository at this point in the history
* Upgrade code to rust 2018 edtion to use async await

* Create test case to ensure struct is send

* Replace all references from Rc to Arc
  • Loading branch information
bltavares authored Feb 17, 2020
1 parent 9790978 commit 5452a3a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 31 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ documentation = "https://docs.rs/merkle-tree-stream"
authors = ["Yoshua Wuyts <[email protected]>"]
license = "MIT OR Apache-2.0"
readme = "README.md"
edition = "2018"

[dependencies]
flat-tree = "4.0.1"
Expand All @@ -15,3 +16,4 @@ flat-tree = "4.0.1"
hex = "0.4.0"
quickcheck = "0.9.0"
crypto-hash = "0.3.1"
async-std = "1.5.0"
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ extern crate rust_sodium;
use merkle_tree_stream::{HashMethods, DefaultNode, MerkleTreeStream, Node,
PartialNode};
use rust_sodium::crypto::hash::sha256;
use std::rc::Rc;
use std::sync::Arc;

struct H;
impl HashMethods for H {
type Node = DefaultNode;
type Hash = Vec<u8>;

fn leaf(&self, leaf: &PartialNode, _roots: &[Rc<Self::Node>]) -> Self::Hash {
fn leaf(&self, leaf: &PartialNode, _roots: &[Arc<Self::Node>]) -> Self::Hash {
let data = leaf.as_ref().unwrap();
sha256::hash(&data).0.to_vec()
}
Expand Down
49 changes: 49 additions & 0 deletions examples/async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use async_std::task;
use merkle_tree_stream::{
DefaultNode, HashMethods, MerkleTreeStream, Node, NodeKind, PartialNode,
};
use std::sync::Arc;
use std::vec::Vec;

struct XorHashMethods;
impl HashMethods for XorHashMethods {
type Node = DefaultNode;
type Hash = Vec<u8>;

fn leaf(&self, leaf: &PartialNode, _roots: &[Arc<Self::Node>]) -> Self::Hash {
// bitwise XOR the data into u8
let hash = match leaf.data() {
NodeKind::Parent => 0,
NodeKind::Leaf(data) => data.iter().fold(0, |acc, x| acc ^ x),
};
vec![hash]
}

fn parent(&self, a: &Self::Node, b: &Self::Node) -> Self::Hash {
let hash = Node::hash(a)
.iter()
.chain(Node::hash(b).iter())
.fold(0, |acc, x| acc ^ x);
vec![hash]
}
}

async fn append<H: HashMethods>(
mts: &mut MerkleTreeStream<H>,
content: &[u8],
nodes: &mut Vec<Arc<H::Node>>,
) {
mts.next(content, nodes);
}

fn main() {
task::block_on(task::spawn(async {
let mut mts = MerkleTreeStream::new(XorHashMethods, Vec::new());
let mut nodes = Vec::new();
append(&mut mts, b"hello", &mut nodes).await;
append(&mut mts, b"hashed", &mut nodes).await;
mts.next(b"world", &mut nodes);

println!("{:?}", nodes);
}));
}
4 changes: 2 additions & 2 deletions examples/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ extern crate merkle_tree_stream;
use merkle_tree_stream::{
DefaultNode, HashMethods, MerkleTreeStream, Node, NodeKind, PartialNode,
};
use std::rc::Rc;
use std::sync::Arc;
use std::vec::Vec;

struct XorHashMethods;
impl HashMethods for XorHashMethods {
type Node = DefaultNode;
type Hash = Vec<u8>;

fn leaf(&self, leaf: &PartialNode, _roots: &[Rc<Self::Node>]) -> Self::Hash {
fn leaf(&self, leaf: &PartialNode, _roots: &[Arc<Self::Node>]) -> Self::Hash {
// bitwise XOR the data into u8
let hash = match leaf.data() {
NodeKind::Parent => 0,
Expand Down
36 changes: 18 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
//! ## Example
//! ```rust
//! use merkle_tree_stream::{DefaultNode, HashMethods, MerkleTreeStream, Node, PartialNode, NodeKind};
//! use std::rc::Rc;
//! use std::sync::Arc;
//! use std::vec::Vec;
//!
//! struct XorHashMethods;
//! impl HashMethods for XorHashMethods {
//! type Node = DefaultNode;
//! type Hash = Vec<u8>;
//!
//! fn leaf(&self, leaf: &PartialNode, _roots: &[Rc<Self::Node>]) -> Self::Hash {
//! fn leaf(&self, leaf: &PartialNode, _roots: &[Arc<Self::Node>]) -> Self::Hash {
//! // bitwise XOR the data into u8
//! let hash = match leaf.data() {
//! NodeKind::Parent => 0,
Expand All @@ -39,10 +39,10 @@ extern crate flat_tree as flat;
mod default_node;
mod partial_node;

pub use default_node::DefaultNode;
pub use partial_node::{NodeKind, PartialNode};
pub use crate::default_node::DefaultNode;
pub use crate::partial_node::{NodeKind, PartialNode};

use std::rc::Rc;
use std::sync::Arc;

/// The parts that make up a full Node from a PartialNode
#[derive(Debug)]
Expand Down Expand Up @@ -80,7 +80,7 @@ pub trait HashMethods {
/// The type of hash returned from the hashing functions.
type Hash;
/// Pass data through a hash function.
fn leaf(&self, leaf: &PartialNode, roots: &[Rc<Self::Node>]) -> Self::Hash;
fn leaf(&self, leaf: &PartialNode, roots: &[Arc<Self::Node>]) -> Self::Hash;
/// Pass hashes through a hash function.
fn parent(&self, a: &Self::Node, b: &Self::Node) -> Self::Hash;
}
Expand All @@ -105,15 +105,15 @@ pub trait Node {
/// ## Example
/// ```rust
/// use merkle_tree_stream::{DefaultNode, HashMethods, MerkleTreeStream, Node, PartialNode, NodeKind};
/// use std::rc::Rc;
/// use std::sync::Arc;
/// use std::vec::Vec;
///
/// struct XorHashMethods;
/// impl HashMethods for XorHashMethods {
/// type Node = DefaultNode;
/// type Hash = Vec<u8>;
///
/// fn leaf(&self, leaf: &PartialNode, _roots: &[Rc<Self::Node>]) -> Self::Hash {
/// fn leaf(&self, leaf: &PartialNode, _roots: &[Arc<Self::Node>]) -> Self::Hash {
/// // bitwise XOR the data into u8
/// let hash = match leaf.data() {
/// NodeKind::Parent => 0,
Expand Down Expand Up @@ -177,13 +177,13 @@ pub trait Node {
#[derive(Debug)]
pub struct MerkleTreeStream<T: HashMethods> {
handler: T,
roots: Vec<Rc<T::Node>>,
roots: Vec<Arc<T::Node>>,
blocks: usize,
}

impl<H: HashMethods> MerkleTreeStream<H> {
/// Create a new MerkleTreeStream instance.
pub fn new(handler: H, roots: Vec<Rc<H::Node>>) -> MerkleTreeStream<H> {
pub fn new(handler: H, roots: Vec<Arc<H::Node>>) -> MerkleTreeStream<H> {
MerkleTreeStream {
handler,
roots,
Expand All @@ -193,7 +193,7 @@ impl<H: HashMethods> MerkleTreeStream<H> {

/// Pass a string buffer through the flat-tree hash functions, and write the
/// result back out to "nodes".
pub fn next<'a>(&mut self, data: &[u8], nodes: &'a mut Vec<Rc<H::Node>>) {
pub fn next<'a>(&mut self, data: &[u8], nodes: &'a mut Vec<Arc<H::Node>>) {
let index: usize = 2 * self.blocks;
self.blocks += 1;

Expand All @@ -206,10 +206,10 @@ impl<H: HashMethods> MerkleTreeStream<H> {

let hash = self.handler.leaf(&leaf, &self.roots);
let parts = NodeParts { node: leaf, hash };
let node = Rc::new(H::Node::from(parts));
let node = Arc::new(H::Node::from(parts));

self.roots.push(Rc::clone(&node));
nodes.push(Rc::clone(&node));
self.roots.push(Arc::clone(&node));
nodes.push(Arc::clone(&node));

while self.roots.len() > 1 {
let leaf = {
Expand Down Expand Up @@ -238,14 +238,14 @@ impl<H: HashMethods> MerkleTreeStream<H> {
self.roots.pop();
}

let leaf = Rc::new(leaf);
self.roots.push(Rc::clone(&leaf));
nodes.push(Rc::clone(&leaf));
let leaf = Arc::new(leaf);
self.roots.push(Arc::clone(&leaf));
nodes.push(Arc::clone(&leaf));
}
}

/// Get the roots vector.
pub fn roots(&self) -> &Vec<Rc<H::Node>> {
pub fn roots(&self) -> &Vec<Arc<H::Node>> {
&self.roots
}
}
18 changes: 9 additions & 9 deletions tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ use merkle_tree_stream::{
use quickcheck::quickcheck;
use std::collections::HashSet;
use std::iter;
use std::rc::Rc;
use std::sync::Arc;

struct H;
impl HashMethods for H {
type Node = DefaultNode;
type Hash = Vec<u8>;

fn leaf(&self, leaf: &PartialNode, _roots: &[Rc<Self::Node>]) -> Self::Hash {
fn leaf(&self, leaf: &PartialNode, _roots: &[Arc<Self::Node>]) -> Self::Hash {
match leaf.data() {
NodeKind::Leaf(data) => {
hex_digest(Algorithm::SHA256, &data).as_bytes().to_vec()
Expand All @@ -39,7 +39,7 @@ impl HashMethods for H {
fn mts_one_node() {
let roots = Vec::new();
let mut mts = MerkleTreeStream::new(H, roots);
let mut nodes: Vec<Rc<DefaultNode>> = Vec::new();
let mut nodes: Vec<Arc<DefaultNode>> = Vec::new();
mts.next(b"hello", &mut nodes);
assert_eq!(1, nodes.len());

Expand All @@ -57,7 +57,7 @@ fn mts_one_node() {
fn mts_more_nodes() {
let roots = Vec::new();
let mut mts = MerkleTreeStream::new(H, roots);
let mut nodes: Vec<Rc<DefaultNode>> = Vec::new();
let mut nodes: Vec<Arc<DefaultNode>> = Vec::new();
mts.next(b"a", &mut nodes);
mts.next(b"b", &mut nodes);

Expand Down Expand Up @@ -115,7 +115,7 @@ fn mts_more_nodes() {
}
}

fn build_mts(data: &[Vec<u8>]) -> (MerkleTreeStream<H>, Vec<Rc<DefaultNode>>) {
fn build_mts(data: &[Vec<u8>]) -> (MerkleTreeStream<H>, Vec<Arc<DefaultNode>>) {
let roots = vec![];
let mut mts = MerkleTreeStream::new(H, roots);
let mut nodes = vec![];
Expand All @@ -124,7 +124,7 @@ fn build_mts(data: &[Vec<u8>]) -> (MerkleTreeStream<H>, Vec<Rc<DefaultNode>>) {
(mts, nodes)
}

fn all_children(index: usize) -> Box<Iterator<Item = usize>> {
fn all_children(index: usize) -> Box<dyn Iterator<Item = usize>> {
let self_ = iter::once(index);
match flat_tree::children(index) {
None => Box::new(self_),
Expand Down Expand Up @@ -218,7 +218,7 @@ fn all_leaves_contain_data() {
#[test]
fn hashes_change_when_data_is_changed() {
/// Finds the parent indices (in-tree IDs) of the nth data block
fn parent_indices(nodes: &[Rc<DefaultNode>], n: usize) -> HashSet<usize> {
fn parent_indices(nodes: &[Arc<DefaultNode>], n: usize) -> HashSet<usize> {
let modified_node_index = nodes
.iter()
.filter(|node| node.data.is_some())
Expand All @@ -240,9 +240,9 @@ fn hashes_change_when_data_is_changed() {
}

fn partition(
nodes: Vec<Rc<DefaultNode>>,
nodes: Vec<Arc<DefaultNode>>,
indices: &HashSet<usize>,
) -> (Vec<Rc<DefaultNode>>, Vec<Rc<DefaultNode>>) {
) -> (Vec<Arc<DefaultNode>>, Vec<Arc<DefaultNode>>) {
nodes
.into_iter()
.partition(|node| indices.contains(&node.index()))
Expand Down

0 comments on commit 5452a3a

Please sign in to comment.