2021-03-10 21:21:50 +00:00
|
|
|
use blakeout::Blakeout;
|
|
|
|
|
|
|
|
use crate::{Block, Bytes, Keystore};
|
2021-03-22 18:20:51 +00:00
|
|
|
use sha2::{Sha256, Digest};
|
2021-04-10 07:47:21 +00:00
|
|
|
use std::convert::TryInto;
|
2021-03-10 21:21:50 +00:00
|
|
|
|
|
|
|
/// Checks block's hash and returns true on valid hash or false otherwise
|
|
|
|
pub fn check_block_hash(block: &Block) -> bool {
|
|
|
|
let mut copy: Block = block.clone();
|
|
|
|
copy.hash = Bytes::default();
|
|
|
|
copy.signature = Bytes::default();
|
|
|
|
let data = serde_json::to_string(©).unwrap();
|
2021-03-22 18:20:51 +00:00
|
|
|
blakeout_data(data.as_bytes()) == block.hash
|
2021-03-10 21:21:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Hashes data by given hasher
|
2021-03-22 18:20:51 +00:00
|
|
|
pub fn blakeout_data(data: &[u8]) -> Bytes {
|
|
|
|
let mut digest = Blakeout::default();
|
|
|
|
digest.update(data);
|
|
|
|
Bytes::from_bytes(digest.result())
|
2021-03-10 21:21:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks block's signature, returns true if the signature is valid, false otherwise
|
|
|
|
pub fn check_block_signature(block: &Block) -> bool {
|
|
|
|
let mut copy = block.clone();
|
|
|
|
copy.signature = Bytes::default();
|
2021-03-12 00:36:54 +00:00
|
|
|
Keystore::check(©.as_bytes(), ©.pub_key, &block.signature)
|
2021-03-10 21:21:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Hashes some identity (domain in case of DNS). If you give it a public key, it will hash with it as well.
|
|
|
|
/// Giving public key is needed to create a confirmation field in [Transaction]
|
|
|
|
pub fn hash_identity(identity: &str, key: Option<&Bytes>) -> Bytes {
|
2021-04-10 07:47:21 +00:00
|
|
|
let base = hash_sha256(identity.as_bytes());
|
|
|
|
let identity = hash_sha256(&base);
|
|
|
|
match key {
|
|
|
|
None => { Bytes::from_bytes(&identity) }
|
|
|
|
Some(key) => {
|
|
|
|
let mut buf = Vec::new();
|
2021-04-11 15:50:55 +00:00
|
|
|
buf.append(&mut base.clone());
|
2021-04-10 07:47:21 +00:00
|
|
|
buf.append(&mut key.to_vec());
|
|
|
|
Bytes::from_bytes(&hash_sha256(&buf))
|
|
|
|
}
|
2021-03-10 21:21:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// There is no default PartialEq implementation for arrays > 32 in size
|
|
|
|
pub fn same_hash(left: &[u8], right: &[u8]) -> bool {
|
|
|
|
if left.len() != right.len() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// We iterate whole slices to eliminate timing attacks
|
|
|
|
let mut result = true;
|
|
|
|
for (x, y) in left.iter().zip(right) {
|
|
|
|
if x != y {
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2021-04-10 18:02:51 +00:00
|
|
|
/// Returns hash difficulty (sum of zeroes from start and end)
|
|
|
|
#[inline]
|
2021-04-10 07:47:21 +00:00
|
|
|
pub fn hash_difficulty(hash: &[u8]) -> u32 {
|
|
|
|
let bytes: [u8; 8] = hash[..8].try_into().unwrap();
|
|
|
|
let int_start = u64::from_be_bytes(bytes);
|
|
|
|
let bytes: [u8; 8] = hash[hash.len() - 8..].try_into().unwrap();
|
|
|
|
let int_end = u64::from_be_bytes(bytes);
|
|
|
|
int_start.leading_zeros() + int_end.trailing_zeros()
|
|
|
|
}
|
|
|
|
|
2021-04-10 18:02:51 +00:00
|
|
|
/// Returns hash difficulty for keys (only from the start)
|
|
|
|
#[inline]
|
2021-04-10 07:47:21 +00:00
|
|
|
pub fn hash_difficulty_key(hash: &[u8]) -> u32 {
|
|
|
|
let bytes: [u8; 8] = hash[..8].try_into().unwrap();
|
|
|
|
let int = u64::from_be_bytes(bytes);
|
|
|
|
int.leading_zeros()
|
|
|
|
}
|
|
|
|
|
2021-04-10 18:02:51 +00:00
|
|
|
/// Hashes data by Sha256 algorithm
|
|
|
|
#[inline]
|
2021-04-10 07:47:21 +00:00
|
|
|
pub fn hash_sha256(data: &[u8]) -> Vec<u8> {
|
|
|
|
let mut digest = Sha256::default();
|
|
|
|
digest.update(data.as_ref());
|
|
|
|
Vec::from(&digest.finalize()[..])
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::blockchain::hash_utils::hash_sha256;
|
|
|
|
use std::convert::TryInto;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
pub fn test_hash() {
|
|
|
|
let id = b"example.com";
|
|
|
|
let key = b"some_key";
|
|
|
|
|
|
|
|
let base = hash_sha256(id);
|
|
|
|
|
|
|
|
let identity = hash_sha256(&base);
|
2021-03-10 21:21:50 +00:00
|
|
|
|
2021-04-10 07:47:21 +00:00
|
|
|
let mut buf = Vec::new();
|
|
|
|
buf.append(&mut identity.clone());
|
|
|
|
buf.append(&mut key.to_vec());
|
|
|
|
let confirmation = hash_sha256(&buf);
|
|
|
|
|
|
|
|
println!("result1 = {:?}", &base);
|
|
|
|
println!("result2 = {:?}", &identity);
|
|
|
|
println!("result3 = {:?}", &confirmation);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_hash_is_good() {
|
|
|
|
let hash = vec!(0u8,0u8,0u8,255,255,255,255,255);
|
|
|
|
let bytes: [u8; 8] = hash[..8].try_into().unwrap();
|
|
|
|
let int = u64::from_be_bytes(bytes);
|
|
|
|
println!("int = {}", int);
|
|
|
|
}
|
2021-03-22 21:57:54 +00:00
|
|
|
}
|