merkle/hashutils.rs
1use crypto::sha3::Sha3;
2use crypto::digest::Digest;
3
4/// The type of values stored in a `MerkleTree` must implement
5/// this trait, in order for them to be able to be fed
6/// to a Ring `Context` when computing the hash of a leaf.
7///
8/// A default instance for types that already implements
9/// `AsRef<[u8]>` is provided.
10///
11/// ## Example
12///
13/// Here is an example of how to implement `Hashable` for a type
14/// that does not (or cannot) implement `AsRef<[u8]>`:
15///
16/// ```ignore
17/// impl Hashable for PublicKey {
18/// fn update_context(&self, context: &mut Context) {
19/// let bytes: Vec<u8> = self.to_bytes();
20/// context.update(&bytes);
21/// }
22/// }
23/// ```
24pub trait Hashable {
25
26 /// Update the given `context` with `self`.
27 ///
28 /// See `ring::digest::Context::update` for more information.
29 fn update_context(&self, context: &mut Sha3);
30
31}
32
33impl <T: AsRef<[u8]>> Hashable for T {
34
35 fn update_context(&self, context: &mut Sha3) {
36 context.input(self.as_ref());
37 }
38}
39
40/// The sole purpose of this trait is to extend the standard
41/// `ring::algo::Algorithm` type with a couple utility functions.
42pub trait HashUtils<U: AsRef<[u8]>> {
43
44 /// Compute the hash of the empty string
45 fn hash_empty(self) -> U;
46
47 /// Compute the hash of the given leaf
48 fn hash_leaf<T>(self, bytes: &T) -> U where T: Hashable;
49
50 /// Compute the hash of the concatenation of `left` and `right`.
51 // XXX: This is overly generic temporarily to make refactoring easier.
52 // TODO: Give `left` and `right` type &Digest.
53 fn hash_nodes<T>(self, left: &T, right: &T) -> U where T: Hashable;
54}
55
56impl<H: From<[u8; 32]> + AsRef<[u8]>> HashUtils<H> for Sha3 {
57 fn hash_empty(mut self) -> H {
58 let mut r: [u8; 32] = [0u8; 32];
59 self.reset();
60 self.input(&[]);
61 self.result(&mut r);
62 r.into()
63 }
64
65 fn hash_leaf<T>(mut self, bytes: &T) -> H where T: Hashable {
66 let mut r: [u8; 32] = [0u8; 32];
67 self.reset();
68 bytes.update_context(&mut self);
69 self.result(&mut r);
70 r.into()
71 }
72
73 fn hash_nodes<T>(mut self, left: &T, right: &T) -> H where T: Hashable {
74 let mut r: [u8; 32] = [0u8; 32];
75 self.reset();
76 left.update_context(&mut self);
77 right.update_context(&mut self);
78 self.result(&mut r);
79 r.into()
80 }
81}