Add SHA3
This commit is contained in:
parent
c08292663f
commit
006fe20287
@ -13,5 +13,5 @@ rustc-serialize = "0.3"
|
|||||||
arrayvec = "0.3"
|
arrayvec = "0.3"
|
||||||
mio = "0.*"
|
mio = "0.*"
|
||||||
rand = "0.*"
|
rand = "0.*"
|
||||||
tiny-keccak = "0.2"
|
tiny-keccak = "0.3"
|
||||||
rocksdb = "0.2.1"
|
rocksdb = "0.2.1"
|
||||||
|
229
src/bytes.rs
229
src/bytes.rs
@ -10,74 +10,91 @@ use std::fmt;
|
|||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use uint::{U128, U256};
|
use uint::{U128, U256};
|
||||||
|
|
||||||
|
pub trait BytesConvertable {
|
||||||
|
fn bytes(&self) -> &[u8];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BytesConvertable for &'a [u8] {
|
||||||
|
fn bytes(&self) -> &[u8] { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BytesConvertable for Vec<u8> {
|
||||||
|
fn bytes(&self) -> &[u8] { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes_convertable() {
|
||||||
|
assert_eq!(vec![0x12u8, 0x34].bytes(), &[0x12u8, 0x34]);
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: optimise some conversations
|
/// TODO: optimise some conversations
|
||||||
pub trait ToBytes {
|
pub trait ToBytes {
|
||||||
fn to_bytes(&self) -> Vec<u8>;
|
fn to_bytes(&self) -> Vec<u8>;
|
||||||
fn to_bytes_len(&self) -> usize { self.to_bytes().len() }
|
fn to_bytes_len(&self) -> usize { self.to_bytes().len() }
|
||||||
fn first_byte(&self) -> Option<u8> { self.to_bytes().first().map(|&x| { x })}
|
fn first_byte(&self) -> Option<u8> { self.to_bytes().first().map(|&x| { x })}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> ToBytes for &'a str {
|
impl <'a> ToBytes for &'a str {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
From::from(*self)
|
From::from(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_bytes_len(&self) -> usize { self.len() }
|
fn to_bytes_len(&self) -> usize { self.len() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToBytes for String {
|
impl ToBytes for String {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
let s: &str = self.as_ref();
|
let s: &str = self.as_ref();
|
||||||
From::from(s)
|
From::from(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_bytes_len(&self) -> usize { self.len() }
|
fn to_bytes_len(&self) -> usize { self.len() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToBytes for u8 {
|
impl ToBytes for u8 {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
match *self {
|
match *self {
|
||||||
0 => vec![],
|
0 => vec![],
|
||||||
_ => vec![*self]
|
_ => vec![*self]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_bytes_len(&self) -> usize {
|
fn to_bytes_len(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
0 => 0,
|
0 => 0,
|
||||||
_ => 1
|
_ => 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn first_byte(&self) -> Option<u8> {
|
fn first_byte(&self) -> Option<u8> {
|
||||||
match *self {
|
match *self {
|
||||||
0 => None,
|
0 => None,
|
||||||
_ => Some(*self)
|
_ => Some(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToBytes for u64 {
|
impl ToBytes for u64 {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut res= vec![];
|
let mut res= vec![];
|
||||||
let count = self.to_bytes_len();
|
let count = self.to_bytes_len();
|
||||||
res.reserve(count);
|
res.reserve(count);
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
let j = count - 1 - i;
|
let j = count - 1 - i;
|
||||||
res.push((*self >> (j * 8)) as u8);
|
res.push((*self >> (j * 8)) as u8);
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 }
|
fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 }
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_map_to_bytes {
|
macro_rules! impl_map_to_bytes {
|
||||||
($from: ident, $to: ty) => {
|
($from: ident, $to: ty) => {
|
||||||
impl ToBytes for $from {
|
impl ToBytes for $from {
|
||||||
fn to_bytes(&self) -> Vec<u8> { (*self as $to).to_bytes() }
|
fn to_bytes(&self) -> Vec<u8> { (*self as $to).to_bytes() }
|
||||||
fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() }
|
fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_map_to_bytes!(usize, u64);
|
impl_map_to_bytes!(usize, u64);
|
||||||
@ -85,21 +102,21 @@ impl_map_to_bytes!(u16, u64);
|
|||||||
impl_map_to_bytes!(u32, u64);
|
impl_map_to_bytes!(u32, u64);
|
||||||
|
|
||||||
macro_rules! impl_uint_to_bytes {
|
macro_rules! impl_uint_to_bytes {
|
||||||
($name: ident) => {
|
($name: ident) => {
|
||||||
impl ToBytes for $name {
|
impl ToBytes for $name {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut res= vec![];
|
let mut res= vec![];
|
||||||
let count = self.to_bytes_len();
|
let count = self.to_bytes_len();
|
||||||
res.reserve(count);
|
res.reserve(count);
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
let j = count - 1 - i;
|
let j = count - 1 - i;
|
||||||
res.push(self.byte(j));
|
res.push(self.byte(j));
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
|
fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_uint_to_bytes!(U256);
|
impl_uint_to_bytes!(U256);
|
||||||
@ -107,17 +124,17 @@ impl_uint_to_bytes!(U128);
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum FromBytesError {
|
pub enum FromBytesError {
|
||||||
UnexpectedEnd
|
UnexpectedEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdError for FromBytesError {
|
impl StdError for FromBytesError {
|
||||||
fn description(&self) -> &str { "from_bytes error" }
|
fn description(&self) -> &str { "from_bytes error" }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FromBytesError {
|
impl fmt::Display for FromBytesError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&self, f)
|
fmt::Debug::fmt(&self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
||||||
@ -126,48 +143,48 @@ pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
|||||||
/// of the return type
|
/// of the return type
|
||||||
/// TODO: check size of bytes before conversation and return appropriate error
|
/// TODO: check size of bytes before conversation and return appropriate error
|
||||||
pub trait FromBytes: Sized {
|
pub trait FromBytes: Sized {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromBytes for String {
|
impl FromBytes for String {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
|
||||||
Ok(::std::str::from_utf8(bytes).unwrap().to_string())
|
Ok(::std::str::from_utf8(bytes).unwrap().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromBytes for u8 {
|
impl FromBytes for u8 {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<u8> {
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<u8> {
|
||||||
match bytes.len() {
|
match bytes.len() {
|
||||||
0 => Ok(0),
|
0 => Ok(0),
|
||||||
_ => Ok(bytes[0])
|
_ => Ok(bytes[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromBytes for u64 {
|
impl FromBytes for u64 {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<u64> {
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<u64> {
|
||||||
match bytes.len() {
|
match bytes.len() {
|
||||||
0 => Ok(0),
|
0 => Ok(0),
|
||||||
l => {
|
l => {
|
||||||
let mut res = 0u64;
|
let mut res = 0u64;
|
||||||
for i in 0..l {
|
for i in 0..l {
|
||||||
let shift = (l - 1 - i) * 8;
|
let shift = (l - 1 - i) * 8;
|
||||||
res = res + ((bytes[i] as u64) << shift);
|
res = res + ((bytes[i] as u64) << shift);
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_map_from_bytes {
|
macro_rules! impl_map_from_bytes {
|
||||||
($from: ident, $to: ident) => {
|
($from: ident, $to: ident) => {
|
||||||
impl FromBytes for $from {
|
impl FromBytes for $from {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$from> {
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$from> {
|
||||||
$to::from_bytes(bytes).map(| x | { x as $from })
|
$to::from_bytes(bytes).map(| x | { x as $from })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_map_from_bytes!(usize, u64);
|
impl_map_from_bytes!(usize, u64);
|
||||||
@ -175,13 +192,13 @@ impl_map_from_bytes!(u16, u64);
|
|||||||
impl_map_from_bytes!(u32, u64);
|
impl_map_from_bytes!(u32, u64);
|
||||||
|
|
||||||
macro_rules! impl_uint_from_bytes {
|
macro_rules! impl_uint_from_bytes {
|
||||||
($name: ident) => {
|
($name: ident) => {
|
||||||
impl FromBytes for $name {
|
impl FromBytes for $name {
|
||||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
||||||
Ok($name::from(bytes))
|
Ok($name::from(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_uint_from_bytes!(U256);
|
impl_uint_from_bytes!(U256);
|
||||||
|
11
src/hash.rs
11
src/hash.rs
@ -6,6 +6,7 @@ use rustc_serialize::hex::*;
|
|||||||
use error::EthcoreError;
|
use error::EthcoreError;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand::os::OsRng;
|
use rand::os::OsRng;
|
||||||
|
use bytes::BytesConvertable;
|
||||||
|
|
||||||
macro_rules! impl_hash {
|
macro_rules! impl_hash {
|
||||||
($from: ident, $size: expr) => {
|
($from: ident, $size: expr) => {
|
||||||
@ -25,6 +26,16 @@ macro_rules! impl_hash {
|
|||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
rng.fill_bytes(&mut self.0);
|
rng.fill_bytes(&mut self.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mut_bytes(&mut self) -> &mut [u8; $size] {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BytesConvertable for $from {
|
||||||
|
fn bytes(&self) -> &[u8] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for $from {
|
impl FromStr for $from {
|
||||||
|
@ -15,6 +15,7 @@ pub mod bytes;
|
|||||||
pub mod rlp;
|
pub mod rlp;
|
||||||
pub mod vector;
|
pub mod vector;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
|
pub mod sha3;
|
||||||
|
|
||||||
//pub mod network;
|
//pub mod network;
|
||||||
|
|
||||||
|
29
src/sha3.rs
Normal file
29
src/sha3.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use std::mem::uninitialized;
|
||||||
|
use tiny_keccak::keccak_256;
|
||||||
|
use bytes::BytesConvertable;
|
||||||
|
use hash::H256;
|
||||||
|
|
||||||
|
trait Hashable {
|
||||||
|
fn sha3(&self) -> H256;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Hashable for T where T: BytesConvertable {
|
||||||
|
fn sha3(&self) -> H256 {
|
||||||
|
unsafe {
|
||||||
|
let mut ret: H256 = uninitialized();
|
||||||
|
keccak_256(self.bytes(), ret.mut_bytes());
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sha3_empty() {
|
||||||
|
use std::str::FromStr;
|
||||||
|
assert_eq!((&[0u8; 0][..]).sha3(), H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn sha3_as() {
|
||||||
|
use std::str::FromStr;
|
||||||
|
assert_eq!((&[0x41u8; 32][..]).sha3(), H256::from_str("59cad5948673622c1d64e2322488bf01619f7ff45789741b15a9f782ce9290a8").unwrap());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user