Skip to content

Commit 895d853

Browse files
committed
made Hash store a byte array, so Node can store a Hash, rather than a byte slice
1 parent c7c8757 commit 895d853

File tree

4 files changed

+72
-43
lines changed

4 files changed

+72
-43
lines changed

src/crypto/hash.rs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
pub use blake2_rfc::blake2b::Blake2bResult;
22

3+
use crate::storage::Node;
34
use blake2_rfc::blake2b::Blake2b;
45
use byteorder::{BigEndian, WriteBytesExt};
56
// use ed25519_dalek::PublicKey;
6-
use crate::storage::Node;
77
use merkle_tree_stream::Node as NodeTrait;
88
use std::convert::AsRef;
9+
use std::fmt;
910
use std::mem;
1011
use std::ops::{Deref, DerefMut};
1112

@@ -14,53 +15,57 @@ const LEAF_TYPE: [u8; 1] = [0x00];
1415
const PARENT_TYPE: [u8; 1] = [0x01];
1516
const ROOT_TYPE: [u8; 1] = [0x02];
1617
//const HYPERCORE: [u8; 9] = *b"hypercore";
18+
const BLAKE_2_HASH_SIZE: usize = 32;
1719

20+
type StoredHash = [u8; BLAKE_2_HASH_SIZE];
1821
/// `BLAKE2b` hash.
19-
#[derive(Debug, Clone, PartialEq)]
22+
/// uses [blake2_rfc::blake2b::Blake2bResult] to hash its inputs on initalisation, the calculated
23+
/// hash is then constant and can not be changed.
24+
#[derive(Debug, Clone, PartialEq, Eq)]
2025
pub struct Hash {
21-
hash: Blake2bResult,
26+
hash: StoredHash,
2227
}
2328

2429
impl Hash {
2530
/// Hash a `Leaf` node.
2631
pub fn from_leaf(data: &[u8]) -> Self {
2732
let size = u64_as_be(data.len() as u64);
2833

29-
let mut hasher = Blake2b::new(32);
34+
let mut hasher = Blake2b::new(BLAKE_2_HASH_SIZE);
3035
hasher.update(&LEAF_TYPE);
3136
hasher.update(&size);
3237
hasher.update(data);
3338

3439
Self {
35-
hash: hasher.finalize(),
40+
hash: hasher_to_stored_hash(hasher),
3641
}
3742
}
3843

3944
/// Hash two `Leaf` nodes hashes together to form a `Parent` hash.
4045
pub fn from_hashes(left: &Node, right: &Node) -> Self {
41-
let (node1, node2) = if left.index <= right.index {
46+
let (node1, node2) = if left <= right {
4247
(left, right)
4348
} else {
4449
(right, left)
4550
};
4651

4752
let size = u64_as_be((node1.length + node2.length) as u64);
4853

49-
let mut hasher = Blake2b::new(32);
54+
let mut hasher = Blake2b::new(BLAKE_2_HASH_SIZE);
5055
hasher.update(&PARENT_TYPE);
5156
hasher.update(&size);
5257
hasher.update(node1.hash());
5358
hasher.update(node2.hash());
5459

5560
Self {
56-
hash: hasher.finalize(),
61+
hash: hasher_to_stored_hash(hasher),
5762
}
5863
}
5964

6065
// /// Hash a public key. Useful to find the key you're looking for on a public
6166
// /// network without leaking the key itself.
6267
// pub fn from_key(public_key: PublicKey) -> Self {
63-
// let mut hasher = Blake2b::new(32);
68+
// let mut hasher = Blake2b::new(BLAKE_2_HASH_SIZE);
6469
// hasher.update(*HYPERCORE);
6570
// hasher.update(public_key.as_bytes());
6671
// Self {
@@ -71,7 +76,7 @@ impl Hash {
7176
/// Hash a vector of `Root` nodes.
7277
// Called `crypto.tree()` in the JS implementation.
7378
pub fn from_roots(roots: &[impl AsRef<Node>]) -> Self {
74-
let mut hasher = Blake2b::new(32);
79+
let mut hasher = Blake2b::new(BLAKE_2_HASH_SIZE);
7580
hasher.update(&ROOT_TYPE);
7681

7782
for node in roots {
@@ -82,14 +87,37 @@ impl Hash {
8287
}
8388

8489
Self {
85-
hash: hasher.finalize(),
90+
hash: hasher_to_stored_hash(hasher),
91+
}
92+
}
93+
94+
pub fn from_bytes(bytes: &[u8]) -> Self {
95+
Self {
96+
hash: slice_to_stored_hash(bytes),
8697
}
8798
}
8899

89100
/// Returns a byte slice of this `Hash`'s contents.
90101
pub fn as_bytes(&self) -> &[u8] {
91-
self.hash.as_bytes()
102+
&self.hash[..]
103+
}
104+
}
105+
106+
fn slice_to_stored_hash(slice: &[u8]) -> StoredHash {
107+
assert!(slice.len() == BLAKE_2_HASH_SIZE);
108+
109+
let mut stored_hash: StoredHash = [0; BLAKE_2_HASH_SIZE];
110+
let mut i = 0;
111+
for byte in slice.iter() {
112+
stored_hash[i] = *byte;
113+
i = i + 1;
92114
}
115+
116+
stored_hash
117+
}
118+
119+
fn hasher_to_stored_hash(hasher: Blake2b) -> StoredHash {
120+
slice_to_stored_hash(hasher.finalize().as_bytes())
93121
}
94122

95123
fn u64_as_be(n: u64) -> [u8; 8] {
@@ -99,7 +127,7 @@ fn u64_as_be(n: u64) -> [u8; 8] {
99127
}
100128

101129
impl Deref for Hash {
102-
type Target = Blake2bResult;
130+
type Target = StoredHash;
103131

104132
fn deref(&self) -> &Self::Target {
105133
&self.hash
@@ -112,6 +140,12 @@ impl DerefMut for Hash {
112140
}
113141
}
114142

143+
impl fmt::Display for Hash {
144+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145+
write!(f, "{:x?}", self.hash)
146+
}
147+
}
148+
115149
#[cfg(test)]
116150
mod tests {
117151
use super::*;
@@ -143,8 +177,8 @@ mod tests {
143177
fn parent_hash() {
144178
let d1: &[u8] = &[0, 1, 2, 3, 4];
145179
let d2: &[u8] = &[42, 43, 44, 45, 46, 47, 48];
146-
let node1 = Node::new(0, Hash::from_leaf(d1).as_bytes().to_vec(), d1.len());
147-
let node2 = Node::new(1, Hash::from_leaf(d2).as_bytes().to_vec(), d2.len());
180+
let node1 = Node::new(0, Hash::from_leaf(d1), d1.len());
181+
let node2 = Node::new(1, Hash::from_leaf(d2), d2.len());
148182
check_hash(
149183
Hash::from_hashes(&node1, &node2),
150184
"6fac58578fa385f25a54c0637adaca71fdfddcea885d561f33d80c4487149a14",
@@ -159,8 +193,8 @@ mod tests {
159193
fn root_hash() {
160194
let d1: &[u8] = &[0, 1, 2, 3, 4];
161195
let d2: &[u8] = &[42, 43, 44, 45, 46, 47, 48];
162-
let node1 = Node::new(0, Hash::from_leaf(d1).as_bytes().to_vec(), d1.len());
163-
let node2 = Node::new(1, Hash::from_leaf(d2).as_bytes().to_vec(), d2.len());
196+
let node1 = Node::new(0, Hash::from_leaf(d1), d1.len());
197+
let node2 = Node::new(1, Hash::from_leaf(d2), d2.len());
164198
check_hash(
165199
Hash::from_roots(&[&node1, &node2]),
166200
"2d117e0bb15c6e5236b6ce764649baed1c41890da901a015341503146cc20bcd",

src/crypto/merkle.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use merkle_tree_stream::{
66
use std::rc::Rc;
77

88
#[derive(Debug)]
9-
struct H;
9+
struct Hasher;
1010

11-
impl HashMethods for H {
11+
impl HashMethods for Hasher {
1212
type Node = Node;
1313
type Hash = Hash;
1414

@@ -33,7 +33,7 @@ impl HashMethods for H {
3333
index: partial.index(),
3434
parent: partial.parent,
3535
length: partial.len(),
36-
hash: hash.as_bytes().into(),
36+
hash: hash,
3737
data,
3838
}
3939
}
@@ -42,7 +42,7 @@ impl HashMethods for H {
4242
/// Merkle Tree Stream
4343
#[derive(Debug)]
4444
pub struct Merkle {
45-
stream: MerkleTreeStream<H>,
45+
stream: MerkleTreeStream<Hasher>,
4646
nodes: Vec<Rc<Node>>,
4747
}
4848

@@ -58,7 +58,7 @@ impl Merkle {
5858
pub fn new() -> Self {
5959
Self {
6060
nodes: vec![],
61-
stream: MerkleTreeStream::new(H, vec![]),
61+
stream: MerkleTreeStream::new(Hasher, vec![]),
6262
}
6363
}
6464

src/feed.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,9 @@ where
287287

288288
let mut visited = vec![];
289289
let mut top = match data {
290-
Some(data) => Node::new(
291-
tree_index(index),
292-
Hash::from_leaf(&data).as_bytes().to_owned(),
293-
data.len(),
294-
),
290+
Some(data) => {
291+
Node::new(tree_index(index), Hash::from_leaf(&data), data.len())
292+
}
295293
None => proof.nodes.remove(0),
296294
};
297295

@@ -322,7 +320,7 @@ where
322320
visited.push(top.clone());
323321
let hash = Hash::from_hashes(&top, &node);
324322
let len = top.len() + node.len();
325-
top = Node::new(flat::parent(top.index), hash.as_bytes().into(), len);
323+
top = Node::new(flat::parent(top.index), hash, len);
326324

327325
if verify_node(&trusted_node, &top) {
328326
self.write(index, data, &visited, None)?;
@@ -526,7 +524,7 @@ where
526524
let node = self.storage.get_node(2 * index)?;
527525
let data = self.storage.get_data(index)?;
528526
let data_hash = Hash::from_leaf(&data);
529-
if node.hash == data_hash.as_bytes() {
527+
if node.hash == data_hash {
530528
valid_blocks += 1;
531529
} else {
532530
invalid_blocks += 1;

src/storage/node.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
use crate::crypto::Hash;
12
use crate::Result;
23
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
34
use flat_tree;
45
use merkle_tree_stream::Node as NodeTrait;
5-
use pretty_hash::fmt as pretty_fmt;
66
use std::cmp::Ordering;
77
use std::convert::AsRef;
88
use std::fmt::{self, Display};
9-
use std::io::Cursor;
9+
use std::io::{Cursor, Seek, SeekFrom};
1010

1111
/// Nodes that are persisted to disk.
1212
// TODO: replace `hash: Vec<u8>` with `hash: Hash`. This requires patching /
@@ -15,7 +15,7 @@ use std::io::Cursor;
1515
#[derive(Debug, Clone, PartialEq, Eq)]
1616
pub struct Node {
1717
pub(crate) index: usize,
18-
pub(crate) hash: Vec<u8>,
18+
pub(crate) hash: Hash,
1919
pub(crate) length: usize,
2020
pub(crate) parent: usize,
2121
pub(crate) data: Option<Vec<u8>>,
@@ -24,7 +24,7 @@ pub struct Node {
2424
impl Node {
2525
/// Create a new instance.
2626
// TODO: ensure sizes are correct.
27-
pub fn new(index: usize, hash: Vec<u8>, length: usize) -> Self {
27+
pub fn new(index: usize, hash: Hash, length: usize) -> Self {
2828
Self {
2929
index,
3030
hash,
@@ -41,16 +41,15 @@ impl Node {
4141
ensure!(buffer.len() == 40, "buffer should be 40 bytes");
4242

4343
let parent = flat_tree::parent(index);
44-
let mut reader = Cursor::new(buffer);
4544

4645
// TODO: subslice directly, move cursor forward.
4746
let capacity = 32;
48-
let mut hash = Vec::with_capacity(capacity);
49-
for _ in 0..capacity {
50-
hash.push(reader.read_u8()?);
51-
}
47+
let hash = Hash::from_bytes(&buffer[..capacity]);
5248

49+
let mut reader = Cursor::new(buffer);
50+
reader.seek(SeekFrom::Start(capacity as u64))?;
5351
// TODO: This will blow up on 32 bit systems, because usize can be 32 bits.
52+
// Note: we could stop using usize on any protocol specific parts of code?
5453
let length = reader.read_u64::<BigEndian>()? as usize;
5554
Ok(Self {
5655
hash,
@@ -64,7 +63,7 @@ impl Node {
6463
/// Convert to a buffer that can be written to disk.
6564
pub fn to_bytes(&self) -> Result<Vec<u8>> {
6665
let mut writer = Vec::with_capacity(40);
67-
writer.extend_from_slice(&self.hash);
66+
writer.extend_from_slice(&self.hash.as_bytes());
6867
writer.write_u64::<BigEndian>(self.length as u64)?;
6968
Ok(writer)
7069
}
@@ -78,7 +77,7 @@ impl NodeTrait for Node {
7877

7978
#[inline]
8079
fn hash(&self) -> &[u8] {
81-
&self.hash
80+
&self.hash.as_bytes()
8281
}
8382

8483
#[inline]
@@ -109,9 +108,7 @@ impl Display for Node {
109108
write!(
110109
f,
111110
"Node {{ index: {}, hash: {}, length: {} }}",
112-
self.index,
113-
pretty_fmt(&self.hash).unwrap(),
114-
self.length
111+
self.index, self.hash, self.length
115112
)
116113
}
117114
}

0 commit comments

Comments
 (0)