Replace libsodium's crypto_generichash_blake2b with blake2b_simd

This commit is contained in:
Jack Grigg 2020-07-14 22:43:09 +12:00
parent ad56e9c2e9
commit 2d172e121f
24 changed files with 273 additions and 163 deletions

1
Cargo.lock generated
View File

@ -495,6 +495,7 @@ name = "librustzcash"
version = "0.2.0"
dependencies = [
"bellman",
"blake2b_simd",
"blake2s_simd",
"bls12_381",
"ed25519-zebra",

View File

@ -21,6 +21,7 @@ crate-type = ["staticlib"]
[dependencies]
bellman = "0.8"
blake2b_simd = "0.5"
blake2s_simd = "0.5"
bls12_381 = "0.3"
group = "0.8"

View File

@ -593,7 +593,7 @@ endif
libzcashconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
libzcashconsensus_la_LIBADD = $(LIBSECP256K1)
libzcashconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
libzcashconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/rust/include -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
libzcashconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
endif

View File

@ -21,6 +21,16 @@
#include "util.h"
void eh_HashState::Update(const unsigned char *input, size_t inputLen)
{
blake2b_update(inner.get(), input, inputLen);
}
void eh_HashState::Finalize(unsigned char *hash, size_t hLen)
{
blake2b_finalize(inner.get(), hash, hLen);
}
// Used in TestEquihashValidator.
void CompressArray(const unsigned char* in, size_t in_len,
@ -143,30 +153,24 @@ std::vector<unsigned char> GetMinimalFromIndices(std::vector<eh_index> indices,
static EhSolverCancelledException solver_cancelled;
template<unsigned int N, unsigned int K>
int Equihash<N,K>::InitialiseState(eh_HashState& base_state)
void Equihash<N,K>::InitialiseState(eh_HashState& base_state)
{
uint32_t le_N = htole32(N);
uint32_t le_K = htole32(K);
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
unsigned char personalization[BLAKE2bPersonalBytes] = {};
memcpy(personalization, "ZcashPoW", 8);
memcpy(personalization+8, &le_N, 4);
memcpy(personalization+12, &le_K, 4);
return crypto_generichash_blake2b_init_salt_personal(&base_state,
NULL, 0, // No key.
(512/N)*N/8,
NULL, // No salt.
personalization);
base_state = eh_HashState((512/N)*N/8, personalization);
}
void GenerateHash(const eh_HashState& base_state, eh_index g,
unsigned char* hash, size_t hLen)
{
eh_HashState state;
state = base_state;
eh_HashState state(base_state);
eh_index lei = htole32(g);
crypto_generichash_blake2b_update(&state, (const unsigned char*) &lei,
sizeof(eh_index));
crypto_generichash_blake2b_final(&state, hash, hLen);
state.Update((const unsigned char*) &lei, sizeof(eh_index));
state.Finalize(hash, hLen);
}
// Big-endian so that lexicographic array comparison is equivalent to integer
@ -724,7 +728,7 @@ invalidsolution:
}
// Explicit instantiations for Equihash<96,3>
template int Equihash<96,3>::InitialiseState(eh_HashState& base_state);
template void Equihash<96,3>::InitialiseState(eh_HashState& base_state);
template bool Equihash<96,3>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<unsigned char>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
@ -733,7 +737,7 @@ template bool Equihash<96,3>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(EhSolverCancelCheck)> cancelled);
// Explicit instantiations for Equihash<200,9>
template int Equihash<200,9>::InitialiseState(eh_HashState& base_state);
template void Equihash<200,9>::InitialiseState(eh_HashState& base_state);
template bool Equihash<200,9>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<unsigned char>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
@ -742,7 +746,7 @@ template bool Equihash<200,9>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(EhSolverCancelCheck)> cancelled);
// Explicit instantiations for Equihash<96,5>
template int Equihash<96,5>::InitialiseState(eh_HashState& base_state);
template void Equihash<96,5>::InitialiseState(eh_HashState& base_state);
template bool Equihash<96,5>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<unsigned char>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);
@ -751,7 +755,7 @@ template bool Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state,
const std::function<bool(EhSolverCancelCheck)> cancelled);
// Explicit instantiations for Equihash<48,5>
template int Equihash<48,5>::InitialiseState(eh_HashState& base_state);
template void Equihash<48,5>::InitialiseState(eh_HashState& base_state);
template bool Equihash<48,5>::BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<unsigned char>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);

View File

@ -32,8 +32,6 @@ void EhIndexToArray(const eh_index i, unsigned char* array);
#include "crypto/sha256.h"
#include "utilstrencodings.h"
#include "sodium.h"
#include <cstring>
#include <exception>
#include <stdexcept>
@ -41,8 +39,35 @@ void EhIndexToArray(const eh_index i, unsigned char* array);
#include <set>
#include <boost/static_assert.hpp>
#include <rust/blake2b.h>
typedef crypto_generichash_blake2b_state eh_HashState;
struct eh_HashState {
std::unique_ptr<BLAKE2bState, decltype(&blake2b_free)> inner;
eh_HashState() : inner(nullptr, blake2b_free) {}
eh_HashState(size_t length, unsigned char personalization[BLAKE2bPersonalBytes]) : inner(blake2b_init(length, personalization), blake2b_free) {}
eh_HashState(eh_HashState&& baseState) : inner(std::move(baseState.inner)) {}
eh_HashState(const eh_HashState& baseState) : inner(blake2b_clone(baseState.inner.get()), blake2b_free) {}
eh_HashState& operator=(eh_HashState&& baseState)
{
if (this != &baseState) {
inner = std::move(baseState.inner);
}
return *this;
}
eh_HashState& operator=(const eh_HashState& baseState)
{
if (this != &baseState) {
inner.reset(blake2b_clone(baseState.inner.get()));
}
return *this;
}
void Update(const unsigned char *input, size_t inputLen);
void Finalize(unsigned char *hash, size_t hLen);
};
eh_index ArrayToEhIndex(const unsigned char* array);
eh_trunc TruncateIndex(const eh_index i, const unsigned int ilen);
@ -188,7 +213,7 @@ public:
Equihash() { }
int InitialiseState(eh_HashState& base_state);
void InitialiseState(eh_HashState& base_state);
bool BasicSolve(const eh_HashState& base_state,
const std::function<bool(std::vector<unsigned char>)> validBlock,
const std::function<bool(EhSolverCancelCheck)> cancelled);

View File

@ -86,10 +86,10 @@ TEST(EquihashTests, IsProbablyDuplicate) {
TEST(EquihashTests, CheckBasicSolverCancelled) {
Equihash<48,5> Eh48_5;
crypto_generichash_blake2b_state state;
eh_HashState state;
Eh48_5.InitialiseState(state);
uint256 V = uint256S("0x00");
crypto_generichash_blake2b_update(&state, V.begin(), V.size());
state.Update(V.begin(), V.size());
{
ASSERT_NO_THROW(Eh48_5.BasicSolve(state, [](std::vector<unsigned char> soln) {
@ -190,10 +190,10 @@ TEST(EquihashTests, CheckBasicSolverCancelled) {
TEST(EquihashTests, CheckOptimisedSolverCancelled) {
Equihash<48,5> Eh48_5;
crypto_generichash_blake2b_state state;
eh_HashState state;
Eh48_5.InitialiseState(state);
uint256 V = uint256S("0x00");
crypto_generichash_blake2b_update(&state, V.begin(), V.size());
state.Update(V.begin(), V.size());
{
ASSERT_NO_THROW(Eh48_5.OptimisedSolve(state, [](std::vector<unsigned char> soln) {

View File

@ -13,10 +13,10 @@
#include "uint256.h"
#include "version.h"
#include "sodium.h"
#include <vector>
#include <rust/blake2b.h>
typedef uint256 ChainCode;
/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */
@ -167,33 +167,31 @@ public:
class CBLAKE2bWriter
{
private:
crypto_generichash_blake2b_state state;
BLAKE2bState* state;
public:
int nType;
int nVersion;
CBLAKE2bWriter(int nTypeIn, int nVersionIn, const unsigned char* personal) : nType(nTypeIn), nVersion(nVersionIn) {
assert(crypto_generichash_blake2b_init_salt_personal(
&state,
NULL, 0, // No key.
32,
NULL, // No salt.
personal) == 0);
state = blake2b_init(32, personal);
}
~CBLAKE2bWriter() {
blake2b_free(state);
}
int GetType() const { return nType; }
int GetVersion() const { return nVersion; }
CBLAKE2bWriter& write(const char *pch, size_t size) {
crypto_generichash_blake2b_update(&state, (const unsigned char*)pch, size);
blake2b_update(state, (const unsigned char*)pch, size);
return (*this);
}
// invalidates the object
uint256 GetHash() {
uint256 result;
crypto_generichash_blake2b_final(&state, (unsigned char*)&result, 32);
blake2b_finalize(state, (unsigned char*)&result, 32);
return result;
}

View File

@ -35,7 +35,6 @@
#include "validationinterface.h"
#include <librustzcash.h>
#include "sodium.h"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
@ -796,7 +795,7 @@ void static BitcoinMiner(const CChainParams& chainparams)
while (true) {
// Hash state
crypto_generichash_blake2b_state state;
eh_HashState state;
EhInitialiseState(n, k, state);
// I = the block header minus nonce and solution.
@ -805,14 +804,12 @@ void static BitcoinMiner(const CChainParams& chainparams)
ss << I;
// H(I||...
crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
state.Update((unsigned char*)&ss[0], ss.size());
// H(I||V||...
crypto_generichash_blake2b_state curr_state;
eh_HashState curr_state;
curr_state = state;
crypto_generichash_blake2b_update(&curr_state,
pblock->nNonce.begin(),
pblock->nNonce.size());
curr_state.Update(pblock->nNonce.begin(), pblock->nNonce.size());
// (x_1, x_2, ...) = A(I, V, n, k)
LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",
@ -860,7 +857,7 @@ void static BitcoinMiner(const CChainParams& chainparams)
if (solver == "tromp") {
// Create solver and initialize it.
equi eq(1);
eq.setstate(&curr_state);
eq.setstate(curr_state.inner.get());
// Initialization done, start algo driver.
eq.digit0(0);

View File

@ -1,7 +1,6 @@
// Equihash solver
// Copyright (c) 2016-2016 John Tromp, The Zcash developers
#include "sodium.h"
#ifdef __APPLE__
#include "pow/tromp/osx_barrier.h"
#endif
@ -11,6 +10,8 @@
#include <string.h> // for functions memset
#include <stdlib.h> // for function qsort
#include <rust/blake2b.h>
typedef uint32_t u32;
typedef unsigned char uchar;
@ -39,16 +40,17 @@ typedef u32 proof[PROOFSIZE];
enum verify_code { POW_OK, POW_DUPLICATE, POW_OUT_OF_ORDER, POW_NONZERO_XOR };
const char *errstr[] = { "OK", "duplicate index", "indices out of order", "nonzero xor" };
void genhash(const crypto_generichash_blake2b_state *ctx, u32 idx, uchar *hash) {
crypto_generichash_blake2b_state state = *ctx;
void genhash(const BLAKE2bState *ctx, u32 idx, uchar *hash) {
auto state = blake2b_clone(ctx);
u32 leb = htole32(idx / HASHESPERBLAKE);
crypto_generichash_blake2b_update(&state, (uchar *)&leb, sizeof(u32));
blake2b_update(state, (uchar *)&leb, sizeof(u32));
uchar blakehash[HASHOUT];
crypto_generichash_blake2b_final(&state, blakehash, HASHOUT);
blake2b_finalize(state, blakehash, HASHOUT);
blake2b_free(state);
memcpy(hash, blakehash + (idx % HASHESPERBLAKE) * WN/8, WN/8);
}
int verifyrec(const crypto_generichash_blake2b_state *ctx, u32 *indices, uchar *hash, int r) {
int verifyrec(const BLAKE2bState *ctx, u32 *indices, uchar *hash, int r) {
if (r == 0) {
genhash(ctx, *indices, hash);
return POW_OK;
@ -90,7 +92,7 @@ bool duped(proof prf) {
}
// verify Wagner conditions
int verify(u32 indices[PROOFSIZE], const crypto_generichash_blake2b_state *ctx) {
int verify(u32 indices[PROOFSIZE], const BLAKE2bState *ctx) {
if (duped(indices))
return POW_DUPLICATE;
uchar hash[WN/8];

View File

@ -204,7 +204,7 @@ u32 min(const u32 a, const u32 b) {
}
struct equi {
crypto_generichash_blake2b_state blake_ctx;
BLAKE2bState* blake_ctx;
htalloc hta;
bsizes *nslots; // PUT IN BUCKET STRUCT
proof *sols;
@ -227,9 +227,10 @@ struct equi {
hta.dealloctrees();
free(nslots);
free(sols);
blake2b_free(blake_ctx);
}
void setstate(const crypto_generichash_blake2b_state *ctx) {
blake_ctx = *ctx;
void setstate(const BLAKE2bState *ctx) {
blake_ctx = blake2b_clone(ctx);
memset(nslots, 0, NBUCKETS * sizeof(au32)); // only nslots[0] needs zeroing
nsols = 0;
}
@ -431,14 +432,15 @@ struct equi {
void digit0(const u32 id) {
uchar hash[HASHOUT];
crypto_generichash_blake2b_state state;
BLAKE2bState* state;
htlayout htl(this, 0);
const u32 hashbytes = hashsize(0);
for (u32 block = id; block < NBLOCKS; block += nthreads) {
state = blake_ctx;
state = blake2b_clone(blake_ctx);
u32 leb = htole32(block);
crypto_generichash_blake2b_update(&state, (uchar *)&leb, sizeof(u32));
crypto_generichash_blake2b_final(&state, hash, HASHOUT);
blake2b_update(state, (uchar *)&leb, sizeof(u32));
blake2b_finalize(state, hash, HASHOUT);
blake2b_free(state);
for (u32 i = 0; i<HASHESPERBLAKE; i++) {
const uchar *ph = hash + i * WN/8;
#if BUCKBITS == 16 && RESTBITS == 4

View File

@ -214,7 +214,7 @@ UniValue generate(const UniValue& params, bool fHelp)
}
// Hash state
crypto_generichash_blake2b_state eh_state;
eh_HashState eh_state;
EhInitialiseState(n, k, eh_state);
// I = the block header minus nonce and solution.
@ -223,7 +223,7 @@ UniValue generate(const UniValue& params, bool fHelp)
ss << I;
// H(I||...
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
eh_state.Update((unsigned char*)&ss[0], ss.size());
while (true) {
// Yes, there is a chance every nonce could fail to satisfy the -regtest
@ -231,11 +231,8 @@ UniValue generate(const UniValue& params, bool fHelp)
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
// H(I||V||...
crypto_generichash_blake2b_state curr_state;
curr_state = eh_state;
crypto_generichash_blake2b_update(&curr_state,
pblock->nNonce.begin(),
pblock->nNonce.size());
eh_HashState curr_state(eh_state);
curr_state.Update(pblock->nNonce.begin(), pblock->nNonce.size());
// (x_1, x_2, ...) = A(I, V, n, k)
std::function<bool(std::vector<unsigned char>)> validBlock =

View File

@ -0,0 +1,59 @@
// Copyright (c) 2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#ifndef BLAKE2B_INCLUDE_H_
#define BLAKE2B_INCLUDE_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
struct BLAKE2bState;
typedef struct BLAKE2bState BLAKE2bState;
#define BLAKE2bPersonalBytes 16U
/// Initializes a BLAKE2b state with no key and no salt.
///
/// `personalization` MUST be a pointer to a 16-byte array.
///
/// Please free this with `blake2b_free` when you are done.
BLAKE2bState* blake2b_init(
size_t output_len,
const unsigned char* personalization);
/// Clones the given BLAKE2b state.
///
/// Both states need to be separately freed with `blake2b_free` when you are
/// done.
BLAKE2bState* blake2b_clone(const BLAKE2bState* state);
/// Frees a BLAKE2b state returned by `blake2b_init`.
void blake2b_free(BLAKE2bState* state);
/// Adds input to the hash. You can call this any number of times.
void blake2b_update(
BLAKE2bState* state,
const unsigned char* input,
size_t input_len);
/// Finalizes the `state` and stores the result in `output`.
///
/// `output_len` MUST be the same value as was passed as the first parameter to
/// `blake2b_init`.
///
/// This method is idempotent, and calling it multiple times will give the same
/// result. It's also possible to call `blake2b_update` with more input in
/// between.
void blake2b_finalize(
BLAKE2bState* state,
unsigned char* output,
size_t output_len);
#ifdef __cplusplus
}
#endif
#endif // BLAKE2B_INCLUDE_H_

53
src/rust/src/blake2b.rs Normal file
View File

@ -0,0 +1,53 @@
// Copyright (c) 2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
use blake2b_simd::{State, PERSONALBYTES};
use libc::{c_uchar, size_t};
use std::ptr;
use std::slice;
#[no_mangle]
pub extern "C" fn blake2b_init(
output_len: size_t,
personalization: *const [c_uchar; PERSONALBYTES],
) -> *mut State {
let personalization = unsafe { personalization.as_ref().unwrap() };
Box::into_raw(Box::new(
blake2b_simd::Params::new()
.hash_length(output_len)
.personal(personalization)
.to_state(),
))
}
#[no_mangle]
pub extern "C" fn blake2b_clone(state: *const State) -> *mut State {
unsafe { state.as_ref() }
.map(|state| Box::into_raw(Box::new(state.clone())))
.unwrap_or(ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn blake2b_free(state: *mut State) {
if !state.is_null() {
drop(unsafe { Box::from_raw(state) });
}
}
#[no_mangle]
pub extern "C" fn blake2b_update(state: *mut State, input: *const c_uchar, input_len: size_t) {
let state = unsafe { state.as_mut().unwrap() };
let input = unsafe { slice::from_raw_parts(input, input_len) };
state.update(input);
}
#[no_mangle]
pub extern "C" fn blake2b_finalize(state: *mut State, output: *mut c_uchar, output_len: size_t) {
let state = unsafe { state.as_mut().unwrap() };
let output = unsafe { slice::from_raw_parts_mut(output, output_len) };
output.copy_from_slice(state.finalize().as_bytes());
}

View File

@ -61,6 +61,7 @@ use zcash_proofs::{
use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree};
mod blake2b;
mod ed25519;
mod tracing_ffi;

View File

@ -14,6 +14,8 @@
#include "script/script.h"
#include "uint256.h"
#include <librustzcash.h>
using namespace std;
typedef vector<unsigned char> valtype;
@ -1057,17 +1059,17 @@ public:
}
};
const unsigned char ZCASH_PREVOUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_PREVOUTS_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','P','r','e','v','o','u','t','H','a','s','h'};
const unsigned char ZCASH_SEQUENCE_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_SEQUENCE_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','S','e','q','u','e','n','c','H','a','s','h'};
const unsigned char ZCASH_OUTPUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_OUTPUTS_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','O','u','t','p','u','t','s','H','a','s','h'};
const unsigned char ZCASH_JOINSPLITS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_JOINSPLITS_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','J','S','p','l','i','t','s','H','a','s','h'};
const unsigned char ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','S','S','p','e','n','d','s','H','a','s','h'};
const unsigned char ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','S','O','u','t','p','u','t','H','a','s','h'};
uint256 GetPrevoutHash(const CTransaction& txTo) {

View File

@ -13,8 +13,6 @@
#include "test/test_bitcoin.h"
#include "uint256.h"
#include "sodium.h"
#include "librustzcash.h"
#include <sstream>
@ -49,12 +47,12 @@ void PrintSolutions(std::stringstream &strm, std::set<std::vector<uint32_t>> sol
#ifdef ENABLE_MINING
void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, const std::set<std::vector<uint32_t>> &solns) {
size_t cBitLen { n/(k+1) };
crypto_generichash_blake2b_state state;
eh_HashState state;
EhInitialiseState(n, k, state);
uint256 V = ArithToUint256(nonce);
BOOST_TEST_MESSAGE("Running solver: n = " << n << ", k = " << k << ", I = " << I << ", V = " << V.GetHex());
crypto_generichash_blake2b_update(&state, (unsigned char*)&I[0], I.size());
crypto_generichash_blake2b_update(&state, V.begin(), V.size());
state.Update((unsigned char*)&I[0], I.size());
state.Update(V.begin(), V.size());
// First test the basic solver
std::set<std::vector<uint32_t>> ret;

View File

@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
unsigned int k = Params().GetConsensus().nEquihashK;
// Hash state
crypto_generichash_blake2b_state eh_state;
eh_HashState eh_state;
EhInitialiseState(n, k, eh_state);
// I = the block header minus nonce and solution.
@ -208,21 +208,18 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
ss << I;
// H(I||...
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
eh_state.Update((unsigned char*)&ss[0], ss.size());
while (true) {
pblock->nNonce = ArithToUint256(try_nonce);
// H(I||V||...
crypto_generichash_blake2b_state curr_state;
curr_state = eh_state;
crypto_generichash_blake2b_update(&curr_state,
pblock->nNonce.begin(),
pblock->nNonce.size());
eh_HashState curr_state(eh_state);
curr_state.Update(pblock->nNonce.begin(), pblock->nNonce.size());
// Create solver and initialize it.
equi eq(1);
eq.setstate(&curr_state);
eq.setstate(curr_state.state);
// Intialization done, start algo driver.
eq.digit0(0);

View File

@ -163,7 +163,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
// Hash state
crypto_generichash_blake2b_state eh_state;
eh_HashState eh_state;
EhInitialiseState(n, k, eh_state);
// I = the block header minus nonce and solution.
@ -172,18 +172,15 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
ss << I;
// H(I||...
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
eh_state.Update((unsigned char*)&ss[0], ss.size());
bool found = false;
do {
block.nNonce = ArithToUint256(UintToArith256(block.nNonce) + 1);
// H(I||V||...
crypto_generichash_blake2b_state curr_state;
curr_state = eh_state;
crypto_generichash_blake2b_update(&curr_state,
block.nNonce.begin(),
block.nNonce.size());
eh_HashState curr_state(eh_state);
curr_state.Update(block.nNonce.begin(), block.nNonce.size());
// (x_1, x_2, ...) = A(I, V, n, k)
std::function<bool(std::vector<unsigned char>)> validBlock =

View File

@ -1,6 +1,5 @@
#include "JoinSplit.hpp"
#include "prf.h"
#include "sodium.h"
#include "zcash/util.h"
@ -18,6 +17,8 @@
#include "streams.h"
#include "version.h"
#include <rust/blake2b.h>
namespace libzcash {
template<size_t NumInputs, size_t NumOutputs>
@ -207,7 +208,7 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
const std::array<uint256, NumInputs>& nullifiers,
const Ed25519VerificationKey& joinSplitPubKey
) {
const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES]
const unsigned char personalization[BLAKE2bPersonalBytes]
= {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'};
std::vector<unsigned char> block(randomSeed.begin(), randomSeed.end());
@ -220,15 +221,10 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
uint256 output;
if (crypto_generichash_blake2b_salt_personal(output.begin(), 32,
&block[0], block.size(),
NULL, 0, // No key.
NULL, // No salt.
personalization
) != 0)
{
throw std::logic_error("hash function failure");
}
auto state = blake2b_init(32, personalization);
blake2b_update(state, &block[0], block.size());
blake2b_finalize(state, output.begin(), 32);
blake2b_free(state);
return output;
}

View File

@ -8,6 +8,8 @@
#include "prf.h"
#include "librustzcash.h"
#include <rust/blake2b.h>
#define NOTEENCRYPTION_CIPHER_KEYSIZE 32
void clamp_curve25519(unsigned char key[crypto_scalarmult_SCALARBYTES])
@ -31,18 +33,13 @@ void PRF_ock(
memcpy(block+64, cm.begin(), 32);
memcpy(block+96, epk.begin(), 32);
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
unsigned char personalization[BLAKE2bPersonalBytes] = {};
memcpy(personalization, "Zcash_Derive_ock", 16);
if (crypto_generichash_blake2b_salt_personal(K, NOTEENCRYPTION_CIPHER_KEYSIZE,
block, 128,
NULL, 0, // No key.
NULL, // No salt.
personalization
) != 0)
{
throw std::logic_error("hash function failure");
}
auto state = blake2b_init(NOTEENCRYPTION_CIPHER_KEYSIZE, personalization);
blake2b_update(state, block, 128);
blake2b_finalize(state, K, NOTEENCRYPTION_CIPHER_KEYSIZE);
blake2b_free(state);
}
void KDF_Sapling(
@ -55,18 +52,13 @@ void KDF_Sapling(
memcpy(block+0, dhsecret.begin(), 32);
memcpy(block+32, epk.begin(), 32);
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
unsigned char personalization[BLAKE2bPersonalBytes] = {};
memcpy(personalization, "Zcash_SaplingKDF", 16);
if (crypto_generichash_blake2b_salt_personal(K, NOTEENCRYPTION_CIPHER_KEYSIZE,
block, 64,
NULL, 0, // No key.
NULL, // No salt.
personalization
) != 0)
{
throw std::logic_error("hash function failure");
}
auto state = blake2b_init(NOTEENCRYPTION_CIPHER_KEYSIZE, personalization);
blake2b_update(state, block, 64);
blake2b_finalize(state, K, NOTEENCRYPTION_CIPHER_KEYSIZE);
blake2b_free(state);
}
void KDF(unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
@ -87,19 +79,14 @@ void KDF(unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
memcpy(block+64, epk.begin(), 32);
memcpy(block+96, pk_enc.begin(), 32);
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
unsigned char personalization[BLAKE2bPersonalBytes] = {};
memcpy(personalization, "ZcashKDF", 8);
memcpy(personalization+8, &nonce, 1);
if (crypto_generichash_blake2b_salt_personal(K, NOTEENCRYPTION_CIPHER_KEYSIZE,
block, 128,
NULL, 0, // No key.
NULL, // No salt.
personalization
) != 0)
{
throw std::logic_error("hash function failure");
}
auto state = blake2b_init(NOTEENCRYPTION_CIPHER_KEYSIZE, personalization);
blake2b_update(state, block, 128);
blake2b_finalize(state, K, NOTEENCRYPTION_CIPHER_KEYSIZE);
blake2b_free(state);
}
namespace libzcash {

View File

@ -13,7 +13,7 @@
namespace libzcash {
const unsigned char ZCASH_SAPLING_FVFP_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_SAPLING_FVFP_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z', 'c', 'a', 's', 'h', 'S', 'a', 'p', 'l', 'i', 'n', 'g', 'F', 'V', 'F', 'P'};
//! Sapling

View File

@ -11,12 +11,12 @@
#include "zcash/prf.h"
#include <librustzcash.h>
#include <sodium.h>
#include <rust/blake2b.h>
const unsigned char ZCASH_HD_SEED_FP_PERSONAL[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_HD_SEED_FP_PERSONAL[BLAKE2bPersonalBytes] =
{'Z', 'c', 'a', 's', 'h', '_', 'H', 'D', '_', 'S', 'e', 'e', 'd', '_', 'F', 'P'};
const unsigned char ZCASH_TADDR_OVK_PERSONAL[crypto_generichash_blake2b_PERSONALBYTES] =
const unsigned char ZCASH_TADDR_OVK_PERSONAL[BLAKE2bPersonalBytes] =
{'Z', 'c', 'T', 'a', 'd', 'd', 'r', 'T', 'o', 'S', 'a', 'p', 'l', 'i', 'n', 'g'};
HDSeed HDSeed::Random(size_t len)
@ -38,16 +38,11 @@ uint256 ovkForShieldingFromTaddr(HDSeed& seed) {
auto rawSeed = seed.RawSeed();
// I = BLAKE2b-512("ZcTaddrToSapling", seed)
crypto_generichash_blake2b_state state;
assert(crypto_generichash_blake2b_init_salt_personal(
&state,
NULL, 0, // No key.
64,
NULL, // No salt.
ZCASH_TADDR_OVK_PERSONAL) == 0);
crypto_generichash_blake2b_update(&state, rawSeed.data(), rawSeed.size());
auto state = blake2b_init(64, ZCASH_TADDR_OVK_PERSONAL);
blake2b_update(state, rawSeed.data(), rawSeed.size());
auto intermediate = std::array<unsigned char, 64>();
crypto_generichash_blake2b_final(&state, intermediate.data(), 64);
blake2b_finalize(state, intermediate.data(), 64);
blake2b_free(state);
// I_L = I[0..32]
uint256 intermediate_L;

View File

@ -4,8 +4,9 @@
#include <array>
#include <librustzcash.h>
#include <rust/blake2b.h>
const unsigned char ZCASH_EXPANDSEED_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] = {'Z','c','a','s','h','_','E','x','p','a','n','d','S','e','e','d'};
const unsigned char ZCASH_EXPANDSEED_PERSONALIZATION[BLAKE2bPersonalBytes] = {'Z','c','a','s','h','_','E','x','p','a','n','d','S','e','e','d'};
// Sapling
std::array<unsigned char, 64> PRF_expand(const uint256& sk, unsigned char t)
@ -15,12 +16,12 @@ std::array<unsigned char, 64> PRF_expand(const uint256& sk, unsigned char t)
memcpy(&blob[0], sk.begin(), 32);
blob[32] = t;
crypto_generichash_blake2b_state state;
crypto_generichash_blake2b_init_salt_personal(&state, nullptr, 0, 64, nullptr, ZCASH_EXPANDSEED_PERSONALIZATION);
crypto_generichash_blake2b_update(&state, blob, 33);
crypto_generichash_blake2b_final(&state, res.data(), 64);
auto state = blake2b_init(64, ZCASH_EXPANDSEED_PERSONALIZATION);
blake2b_update(state, blob, 33);
blake2b_finalize(state, res.data(), 64);
blake2b_free(state);
return res;
}
@ -74,11 +75,11 @@ std::array<unsigned char, 11> default_diversifier(const uint256& sk)
blob[33] = 0;
while (true) {
crypto_generichash_blake2b_state state;
crypto_generichash_blake2b_init_salt_personal(&state, nullptr, 0, 64, nullptr, ZCASH_EXPANDSEED_PERSONALIZATION);
crypto_generichash_blake2b_update(&state, blob, 34);
crypto_generichash_blake2b_final(&state, res.data(), 11);
auto state = blake2b_init(64, ZCASH_EXPANDSEED_PERSONALIZATION);
blake2b_update(state, blob, 34);
blake2b_finalize(state, res.data(), 11);
blake2b_free(state);
if (librustzcash_check_diversifier(res.data())) {
break;
} else if (blob[33] == 255) {

View File

@ -23,7 +23,6 @@
#include "random.h"
#include "rpc/server.h"
#include "script/sign.h"
#include "sodium.h"
#include "streams.h"
#include "txdb.h"
#include "utiltest.h"
@ -160,14 +159,12 @@ double benchmark_solve_equihash()
auto params = Params(CBaseChainParams::MAIN).GetConsensus();
unsigned int n = params.nEquihashN;
unsigned int k = params.nEquihashK;
crypto_generichash_blake2b_state eh_state;
eh_HashState eh_state;
EhInitialiseState(n, k, eh_state);
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
eh_state.Update((unsigned char*)&ss[0], ss.size());
uint256 nonce = GetRandHash();
crypto_generichash_blake2b_update(&eh_state,
nonce.begin(),
nonce.size());
eh_state.Update(nonce.begin(), nonce.size());
struct timeval tv_start;
timer_start(tv_start);