diff --git a/Cargo.toml b/Cargo.toml index a38ed60e9..1b87dfac8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ grin_grin = { path = "./grin" } grin_config = { path = "./config" } secp256k1zkp = { path = "./secp256k1zkp" } +blake2-rfc = "~0.2.17" clap = "^2.23.3" daemonize = "^0.2.3" env_logger="^0.3.5" @@ -20,6 +21,3 @@ log = "^0.3" serde = "~1.0.8" serde_derive = "~1.0.8" serde_json = "~1.0.2" -tiny-keccak = "1.1" - - diff --git a/core/Cargo.toml b/core/Cargo.toml index 2531fac1f..9d5412785 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -6,6 +6,7 @@ workspace = ".." [dependencies] bitflags = "~0.7.0" +blake2-rfc = "~0.2.17" byteorder = "^0.5" num-bigint = "^0.1.35" rust-crypto = "^0.2" @@ -13,6 +14,5 @@ rand = "^0.3" serde = "~1.0.8" serde_derive = "~1.0.8" time = "^0.1" -tiny-keccak = "1.1" secp256k1zkp = { path = "../secp256k1zkp" } diff --git a/core/src/core/hash.rs b/core/src/core/hash.rs index 8800eefab..234553778 100644 --- a/core/src/core/hash.rs +++ b/core/src/core/hash.rs @@ -19,9 +19,10 @@ use std::cmp::min; use std::{fmt, ops}; -use tiny_keccak::Keccak; use std::convert::AsRef; +use blake2::blake2b::Blake2b; + use ser::{self, Reader, Readable, Writer, Writeable, Error, AsFixedBytes}; /// A hash consisting of all zeroes, used as a sentinel. No known preimage. @@ -129,28 +130,28 @@ impl Writeable for Hash { /// Serializer that outputs a hash of the serialized object pub struct HashWriter { - state: Keccak, + state: Blake2b, } impl HashWriter { /// Consume the `HashWriter`, outputting its current hash into a 32-byte /// array pub fn finalize(self, output: &mut [u8]) { - self.state.finalize(output); + output.copy_from_slice(self.state.finalize().as_bytes()); } /// Consume the `HashWriter`, outputting a `Hash` corresponding to its /// current state pub fn into_hash(self) -> Hash { - let mut new_hash = ZERO_HASH; - self.state.finalize(&mut new_hash.0[..]); - new_hash + let mut res = [0; 32]; + (&mut res).copy_from_slice(self.state.finalize().as_bytes()); + Hash(res) } } impl Default for HashWriter { fn default() -> HashWriter { - HashWriter { state: Keccak::new_sha3_256() } + HashWriter { state: Blake2b::new(32) } } } diff --git a/core/src/lib.rs b/core/src/lib.rs index e2b1bc50b..63cccb9ed 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -23,6 +23,7 @@ #[macro_use] extern crate bitflags; +extern crate blake2_rfc as blake2; extern crate byteorder; extern crate crypto; extern crate num_bigint as bigint; @@ -32,7 +33,6 @@ extern crate serde; #[macro_use] extern crate serde_derive; extern crate time; -extern crate tiny_keccak; #[macro_use] pub mod macros; diff --git a/doc/pow/pow.md b/doc/pow/pow.md index c0c67522b..c469cf36c 100644 --- a/doc/pow/pow.md +++ b/doc/pow/pow.md @@ -124,7 +124,7 @@ The Cuckoo Cycle outlined above forms the basis of Grin's mining process, howeve In order to provide additional difficulty control in a manner that meets the needs of a network with constantly evolving hashpower availability, a further Hashcash-based difficulty check is applied to potential solution sets as follows: -If the SHA3-256 (Keccak) hash +If the Blake2b hash of a potential set of solution nonces (currently an array of 42 u32s representing the cycle nonces,) is less than an evolving difficulty target T, then the solution is considered valid. More precisely, the proof difficulty is calculated as the maximum target hash (2^256) divided by the current hash, @@ -174,11 +174,11 @@ valid Proofs-of-Work to create the latest block in the chain. The following is a of a solution appearing in the graph * The Cuckoo Cycle detection algorithm tries to find a solution (i.e. a cycle of length 42) within the generated graph. - * If a cycle is found, a SHA3-256 hash of the proof is created and is compared to the current target + * If a cycle is found, a Blake2b hash of the proof is created and is compared to the current target difficulty, as outlined in [Additional Difficulty Control](#additional-difficulty-control) above. - * If the SHA3-256 Hash difficulty is greater than or equal to the target difficulty, the block is sent to the + * If the Blake2b Hash difficulty is greater than or equal to the target difficulty, the block is sent to the transaction pool, propogated amongst peers for validation, and work begins on the next block. - * If the SHA3-256 Hash difficulty is less than the target difficulty, the proof is thrown out and the timed loop continues. + * If the Blake2b Hash difficulty is less than the target difficulty, the proof is thrown out and the timed loop continues. * If no solution is found, increment the nonce in the header by 1, and update the header's timestamp so the next iteration hashes a different value for seeding the next loop's graph generation step. * If the loop times out with no solution found, start over again from the top, collecting new transactions and creating @@ -229,7 +229,7 @@ every time while larger miners can move on as soon as they find a solution. So i a POW that requires multiple solution attempts with each attempt taking a relatively small amount of time is desirable. Following from the this, Grin's progress-freeness is due to the fact that a solution to a Cuckoo with Grin's default parameters -can typically be found in under a second on most GPUs, and there is the additional requirement of the SHA3-256 difficulty check +can typically be found in under a second on most GPUs, and there is the additional requirement of the Blake2b difficulty check on top of that. Members of a pool are thus able to prove they're working on a solution to a block by submitting valid Cuckoo solutions (or a small bundle of them) that simply fall under the current network target difficulty. diff --git a/grin/tests/framework.rs b/grin/tests/framework.rs index 3bc82ea45..e2e77935b 100644 --- a/grin/tests/framework.rs +++ b/grin/tests/framework.rs @@ -19,8 +19,8 @@ extern crate grin_chain as chain; extern crate grin_api as api; extern crate grin_wallet as wallet; extern crate secp256k1zkp as secp; -extern crate tiny_keccak; +extern crate blake2; extern crate env_logger; extern crate futures; extern crate tokio_core; @@ -35,6 +35,7 @@ use std::fs; use std::sync::{Arc, Mutex, RwLock}; use std::ops::Deref; +use blake2::blake2b::blake2b; use futures::{Future}; use futures::future::join_all; use futures::task::park; @@ -44,7 +45,6 @@ use tokio_core::reactor::Handle; use tokio_timer::Timer; use secp::Secp256k1; -use tiny_keccak::Keccak; use wallet::WalletConfig; use core::consensus; @@ -269,10 +269,7 @@ impl LocalServerContainer { //Just use the name of the server for a seed for now let seed = format!("{}", self.config.name); - let mut sha3 = Keccak::new_sha3_256(); - sha3.update(seed.as_bytes()); - let mut seed = [0; 32]; - sha3.finalize(&mut seed); + let seed = blake2b(32, &[], seed.as_bytes()); let s = Secp256k1::new(); let key = wallet::ExtendedKey::from_seed(&s, &seed[..]) @@ -523,4 +520,4 @@ impl LocalServerContainerPool { } } -} \ No newline at end of file +} diff --git a/src/bin/grin.rs b/src/bin/grin.rs index c8d9090ff..97ba58b7c 100644 --- a/src/bin/grin.rs +++ b/src/bin/grin.rs @@ -21,7 +21,7 @@ extern crate log; extern crate env_logger; extern crate serde; extern crate serde_json; -extern crate tiny_keccak; +extern crate blake2; extern crate grin_api as api; extern crate grin_grin as grin; @@ -34,8 +34,8 @@ use std::thread; use std::io::Read; use std::fs::File; use std::time::Duration; -use tiny_keccak::Keccak; +use blake2::blake2b::blake2b; use clap::{Arg, App, SubCommand, ArgMatches}; use daemonize::Daemonize; @@ -264,10 +264,7 @@ fn wallet_command(wallet_args: &ArgMatches) { let hd_seed = wallet_args.value_of("pass").expect("Wallet passphrase required."); // TODO do something closer to BIP39, eazy solution right now - let mut sha3 = Keccak::new_sha3_256(); - sha3.update(hd_seed.as_bytes()); - let mut seed = [0; 32]; - sha3.finalize(&mut seed); + let seed = blake2b(32, &[], hd_seed.as_bytes()); let s = Secp256k1::new(); let key = wallet::ExtendedKey::from_seed(&s, &seed[..])