core: move Hash into its own module

This commit is contained in:
Merope Riddle 2016-10-22 22:08:53 +00:00
parent 7e2b271865
commit 88b07791fa
5 changed files with 102 additions and 66 deletions

83
core/src/core/hash.rs Normal file
View file

@ -0,0 +1,83 @@
// Copyright 2016 The Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Hash Function
//!
//! Primary hash function used in the protocol
//!
use std::fmt;
use tiny_keccak::Keccak;
/// A hash to uniquely (or close enough) identify one of the main blockchain
/// constructs. Used pervasively for blocks, transactions and ouputs.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct Hash(pub [u8; 32]);
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for i in self.0[..].iter().cloned() {
try!(write!(f, "{:02x}", i));
}
Ok(())
}
}
impl Hash {
/// Creates a new hash from a vector
pub fn from_vec(v: Vec<u8>) -> Hash {
let mut a = [0; 32];
for i in 0..a.len() {
a[i] = v[i];
}
Hash(a)
}
/// Converts the hash to a byte vector
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
/// Converts the hash to a byte slice
pub fn to_slice(&self) -> &[u8] {
&self.0
}
}
pub const ZERO_HASH: Hash = Hash([0; 32]);
/// A trait for types that get their hash (double SHA256) from their byte
/// serialzation.
pub trait Hashed {
fn hash(&self) -> Hash {
let data = self.bytes();
Hash(sha3(data))
}
fn bytes(&self) -> Vec<u8>;
}
fn sha3(data: Vec<u8>) -> [u8; 32] {
let mut sha3 = Keccak::new_sha3_256();
let mut buf = [0; 32];
sha3.update(&data);
sha3.finalize(&mut buf);
buf
}
impl Hashed for [u8] {
fn bytes(&self) -> Vec<u8> {
self.to_owned()
}
}

View file

@ -14,9 +14,12 @@
//! Core types
pub mod hash;
#[allow(dead_code)]
#[macro_use]
mod ser;
use self::hash::{Hash, Hashed, ZERO_HASH};
use ser::{Writeable, Writer, Error, ser_vec};
use time;
@ -41,60 +44,6 @@ pub const BLOCK_TIME_SEC: u8 = 15;
/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;
/// A hash to uniquely (or close enough) identify one of the main blockchain
/// constructs. Used pervasively for blocks, transactions and ouputs.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct Hash(pub [u8; 32]);
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for i in self.0[..].iter().cloned() {
try!(write!(f, "{:02x}", i));
}
Ok(())
}
}
impl Hash {
/// Creates a new hash from a vector
pub fn from_vec(v: Vec<u8>) -> Hash {
let mut a = [0; 32];
for i in 0..a.len() {
a[i] = v[i];
}
Hash(a)
}
/// Converts the hash to a byte vector
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
/// Converts the hash to a byte slice
pub fn to_slice(&self) -> &[u8] {
&self.0
}
}
pub const ZERO_HASH: Hash = Hash([0; 32]);
/// A trait for types that get their hash (double SHA256) from their byte
/// serialzation.
pub trait Hashed {
fn hash(&self) -> Hash {
let data = self.bytes();
Hash(sha3(data))
}
fn bytes(&self) -> Vec<u8>;
}
fn sha3(data: Vec<u8>) -> [u8; 32] {
let mut sha3 = Keccak::new_sha3_256();
let mut buf = [0; 32];
sha3.update(&data);
sha3.finalize(&mut buf);
buf
}
/// Implemented by types that hold inputs and outputs including Pedersen
/// commitments. Handles the collection of the commitments as well as their
/// summing, taking potential explicit overages of fees into account.
@ -755,7 +704,7 @@ impl MerkleRow {
}
fn root(&self) -> Hash {
if self.0.len() == 0 {
Hash(sha3(vec![]))
vec![].hash()
} else if self.0.len() == 1 {
self.0[0].hash()
} else {
@ -767,6 +716,7 @@ impl MerkleRow {
#[cfg(test)]
mod test {
use super::*;
use super::hash::{Hash, Hashed, ZERO_HASH};
use secp;
use secp::Secp256k1;
use secp::key::SecretKey;

View file

@ -19,7 +19,7 @@
use time;
use std::io::{Write, Read};
use core;
use core::{self, hash};
use ser::*;
use secp::Signature;
@ -43,7 +43,7 @@ impl_slice_bytes!(Signature);
impl_slice_bytes!(Commitment);
impl_slice_bytes!(Vec<u8>);
impl AsFixedBytes for core::Hash {
impl AsFixedBytes for hash::Hash {
fn as_fixed_bytes(&self) -> &[u8] {
self.to_slice()
}
@ -124,7 +124,7 @@ impl Writeable for core::Block {
impl Readable<core::Input> for core::Input {
fn read(reader: &mut Reader) -> Result<core::Input, Error> {
reader.read_fixed_bytes(32)
.map(|h| core::Input::BareInput { output: core::Hash::from_vec(h) })
.map(|h| core::Input::BareInput { output: hash::Hash::from_vec(h) })
}
}
@ -210,14 +210,14 @@ impl Readable<core::Block> for core::Block {
Ok(core::Block {
header: core::BlockHeader {
height: height,
previous: core::Hash::from_vec(previous),
previous: hash::Hash::from_vec(previous),
timestamp: time::at_utc(time::Timespec {
sec: timestamp,
nsec: 0,
}),
td: td,
utxo_merkle: core::Hash::from_vec(utxo_merkle),
tx_merkle: core::Hash::from_vec(tx_merkle),
utxo_merkle: hash::Hash::from_vec(utxo_merkle),
tx_merkle: hash::Hash::from_vec(tx_merkle),
total_fees: total_fees,
pow: core::Proof(pow),
nonce: nonce,
@ -237,6 +237,7 @@ mod test {
use secp::*;
use secp::key::*;
use core::*;
use core::hash::ZERO_HASH;
use rand::Rng;
use rand::os::OsRng;

View file

@ -31,7 +31,7 @@ pub fn genesis() -> core::Block {
core::Block {
header: core::BlockHeader {
height: 0,
previous: core::ZERO_HASH,
previous: core::hash::ZERO_HASH,
timestamp: time::Tm {
tm_year: 1997,
tm_mon: 7,
@ -39,8 +39,8 @@ pub fn genesis() -> core::Block {
..time::empty_tm()
},
td: 0,
utxo_merkle: core::Hash::from_vec(empty_h.to_vec()),
tx_merkle: core::Hash::from_vec(empty_h.to_vec()),
utxo_merkle: core::hash::Hash::from_vec(empty_h.to_vec()),
tx_merkle: core::hash::Hash::from_vec(empty_h.to_vec()),
total_fees: 0,
nonce: 0,
pow: core::Proof::zero(), // TODO get actual PoW solution

View file

@ -27,7 +27,8 @@ mod cuckoo;
use time;
use core::{Block, BlockHeader, Hashed, Hash, Proof, PROOFSIZE};
use core::{Block, BlockHeader, Proof, PROOFSIZE};
use core::hash::{Hash, Hashed};
use pow::cuckoo::{Cuckoo, Miner, Error};
use ser;
@ -175,7 +176,8 @@ fn pow_size(b: &Block, target: Proof, sizeshift: u32) -> Result<(Proof, u64), Er
#[cfg(test)]
mod test {
use super::*;
use core::{BlockHeader, Hash, Proof};
use core::{BlockHeader, Proof};
use core::hash::Hash;
use std::time::Instant;
use genesis;