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}