|
|
|
use blakeout::Blakeout;
|
|
|
|
use num_bigint::BigUint;
|
|
|
|
use num_traits::One;
|
|
|
|
|
|
|
|
use crate::{Block, Bytes, Keystore};
|
|
|
|
use sha2::{Sha256, Digest};
|
|
|
|
|
|
|
|
/// 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();
|
|
|
|
blakeout_data(data.as_bytes()) == block.hash
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Hashes data by given hasher
|
|
|
|
pub fn blakeout_data(data: &[u8]) -> Bytes {
|
|
|
|
let mut digest = Blakeout::default();
|
|
|
|
digest.update(data);
|
|
|
|
Bytes::from_bytes(digest.result())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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();
|
|
|
|
Keystore::check(©.as_bytes(), ©.pub_key, &block.signature)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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 {
|
|
|
|
let mut digest = Sha256::default();
|
|
|
|
digest.update(identity.as_bytes());
|
|
|
|
if let Some(key) = key {
|
|
|
|
digest.update(key.as_slice());
|
|
|
|
}
|
|
|
|
Bytes::from_bytes(&digest.finalize()[..])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks if this hash contains enough zeroes
|
|
|
|
pub fn hash_is_good(hash: &[u8], difficulty: usize) -> bool {
|
|
|
|
let target = BigUint::one() << ((hash.len() << 3) - difficulty);
|
|
|
|
let hash_int = BigUint::from_bytes_be(&hash);
|
|
|
|
|
|
|
|
return hash_int < target;
|
|
|
|
}
|