1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pub use ursa::hash::sha2::Digest;

use super::ValidationError;

/// Derive a new hash type
#[macro_export]
macro_rules! hash_type {
    ($modname:ident, $digest:path, $doc:expr) => {
        #[doc=$doc]
        #[allow(non_snake_case)]
        pub mod $modname {
            use once_cell::sync::Lazy;
            use ursa::hash::sha2::Digest;

            pub type DigestType = $digest;

            pub fn digest<V: AsRef<[u8]>>(input: V) -> Vec<u8> {
                DigestType::digest(input.as_ref()).to_vec()
            }

            pub fn digest_empty() -> &'static [u8] {
                static EMPTY_HASH_BYTES: Lazy<Vec<u8>> = Lazy::new(|| digest(&[]));
                EMPTY_HASH_BYTES.as_slice()
            }

            pub fn output_size() -> usize {
                DigestType::output_size()
            }
        }
    }
}

hash_type!(SHA256, ursa::hash::sha2::Sha256, "Sha256 hash");

/// A trait for producing hashes of merkle tree leaves and nodes
pub trait TreeHash {
    fn hash_leaf<T>(leaf: &T) -> Result<Vec<u8>, ValidationError>
    where
        T: Hashable;

    fn hash_nodes<T>(left: &T, right: &T) -> Result<Vec<u8>, ValidationError>
    where
        T: Hashable;
}

impl<H: Digest> TreeHash for H {
    fn hash_leaf<T>(leaf: &T) -> Result<Vec<u8>, ValidationError>
    where
        T: Hashable,
    {
        let mut ctx = Self::new();
        ctx.input(&[0x00]);
        leaf.update_context(&mut ctx)?;
        Ok(ctx.result().to_vec())
    }

    fn hash_nodes<T>(left: &T, right: &T) -> Result<Vec<u8>, ValidationError>
    where
        T: Hashable,
    {
        let mut ctx = Self::new();
        ctx.input(&[0x01]);
        left.update_context(&mut ctx)?;
        right.update_context(&mut ctx)?;
        Ok(ctx.result().to_vec())
    }
}

/// The type of values stored in a `MerkleTree` must implement
/// this trait, in order for them to be able to be fed
/// to a Ring `Context` when computing the hash of a leaf.
///
/// A default instance for types that already implements
/// `AsRef<[u8]>` is provided.
///
/// ## Example
///
/// Here is an example of how to implement `Hashable` for a type
/// that does not (or cannot) implement `AsRef<[u8]>`:
///
/// ```ignore
/// impl Hashable for PublicKey {
///     fn update_context(&self, context: &mut Hasher) -> Result<(), CommonError> {
///         let bytes: Vec<u8> = self.to_bytes();
///         Ok(context.update(&bytes)?)
///     }
/// }
/// ```
pub trait Hashable {
    /// Update the given `context` with `self`.
    ///
    /// See `openssl::hash::Hasher::update` for more information.
    fn update_context<D: Digest>(&self, context: &mut D) -> Result<(), ValidationError>;
}

impl<T: AsRef<[u8]>> Hashable for T {
    fn update_context<D: Digest>(&self, context: &mut D) -> Result<(), ValidationError> {
        Ok(context.input(self.as_ref()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn hash_check_sha256() {
        assert_eq!(SHA256::output_size(), 32);
        assert_eq!(
            SHA256::digest_empty(),
            &[
                227, 176, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36, 39,
                174, 65, 228, 100, 155, 147, 76, 164, 149, 153, 27, 120, 82, 184, 85,
            ]
        );
    }
}