From 2d172e121fd5aac221d71ccfa143b596052af15f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 14 Jul 2020 22:43:09 +1200 Subject: [PATCH] Replace libsodium's crypto_generichash_blake2b with blake2b_simd --- Cargo.lock | 1 + Cargo.toml | 1 + src/Makefile.am | 2 +- src/crypto/equihash.cpp | 36 +++++++++++--------- src/crypto/equihash.h | 33 +++++++++++++++--- src/gtest/test_equihash.cpp | 8 ++--- src/hash.h | 20 +++++------ src/miner.cpp | 13 +++----- src/pow/tromp/equi.h | 16 +++++---- src/pow/tromp/equi_miner.h | 16 +++++---- src/rpc/mining.cpp | 11 +++--- src/rust/include/rust/blake2b.h | 59 +++++++++++++++++++++++++++++++++ src/rust/src/blake2b.rs | 53 +++++++++++++++++++++++++++++ src/rust/src/rustzcash.rs | 1 + src/script/interpreter.cpp | 14 ++++---- src/test/equihash_tests.cpp | 8 ++--- src/test/miner_tests.cpp | 13 +++----- src/test/test_bitcoin.cpp | 11 +++--- src/zcash/JoinSplit.cpp | 18 ++++------ src/zcash/NoteEncryption.cpp | 47 ++++++++++---------------- src/zcash/address/sapling.cpp | 2 +- src/zcash/address/zip32.cpp | 19 ++++------- src/zcash/prf.cpp | 25 +++++++------- src/zcbenchmarks.cpp | 9 ++--- 24 files changed, 273 insertions(+), 163 deletions(-) create mode 100644 src/rust/include/rust/blake2b.h create mode 100644 src/rust/src/blake2b.rs diff --git a/Cargo.lock b/Cargo.lock index f01757ad4..5b951e6bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -495,6 +495,7 @@ name = "librustzcash" version = "0.2.0" dependencies = [ "bellman", + "blake2b_simd", "blake2s_simd", "bls12_381", "ed25519-zebra", diff --git a/Cargo.toml b/Cargo.toml index a365fdb15..3392ee916 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/Makefile.am b/src/Makefile.am index 35a657f5d..b7e7026a7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index bfe14c769..39aafbfda 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -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 GetMinimalFromIndices(std::vector indices, static EhSolverCancelledException solver_cancelled; template -int Equihash::InitialiseState(eh_HashState& base_state) +void Equihash::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)> validBlock, const std::function cancelled); @@ -733,7 +737,7 @@ template bool Equihash<96,3>::OptimisedSolve(const eh_HashState& base_state, const std::function 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)> validBlock, const std::function cancelled); @@ -742,7 +746,7 @@ template bool Equihash<200,9>::OptimisedSolve(const eh_HashState& base_state, const std::function 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)> validBlock, const std::function cancelled); @@ -751,7 +755,7 @@ template bool Equihash<96,5>::OptimisedSolve(const eh_HashState& base_state, const std::function 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)> validBlock, const std::function cancelled); diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index cbcfb8b00..8e30778a9 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -32,8 +32,6 @@ void EhIndexToArray(const eh_index i, unsigned char* array); #include "crypto/sha256.h" #include "utilstrencodings.h" -#include "sodium.h" - #include #include #include @@ -41,8 +39,35 @@ void EhIndexToArray(const eh_index i, unsigned char* array); #include #include +#include -typedef crypto_generichash_blake2b_state eh_HashState; +struct eh_HashState { + std::unique_ptr 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)> validBlock, const std::function cancelled); diff --git a/src/gtest/test_equihash.cpp b/src/gtest/test_equihash.cpp index bb692730f..c4e0320af 100644 --- a/src/gtest/test_equihash.cpp +++ b/src/gtest/test_equihash.cpp @@ -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 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 soln) { diff --git a/src/hash.h b/src/hash.h index fe1607277..731fb6a6e 100644 --- a/src/hash.h +++ b/src/hash.h @@ -13,10 +13,10 @@ #include "uint256.h" #include "version.h" -#include "sodium.h" - #include +#include + 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; } diff --git a/src/miner.cpp b/src/miner.cpp index 3a1af0fd1..de398784a 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -35,7 +35,6 @@ #include "validationinterface.h" #include -#include "sodium.h" #include #include @@ -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); diff --git a/src/pow/tromp/equi.h b/src/pow/tromp/equi.h index f6d8803c2..a5460d26d 100644 --- a/src/pow/tromp/equi.h +++ b/src/pow/tromp/equi.h @@ -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 // for functions memset #include // for function qsort +#include + 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]; diff --git a/src/pow/tromp/equi_miner.h b/src/pow/tromp/equi_miner.h index ae527827a..0698656c5 100644 --- a/src/pow/tromp/equi_miner.h +++ b/src/pow/tromp/equi_miner.h @@ -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; inNonce = 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)> validBlock = diff --git a/src/rust/include/rust/blake2b.h b/src/rust/include/rust/blake2b.h new file mode 100644 index 000000000..f48f9981e --- /dev/null +++ b/src/rust/include/rust/blake2b.h @@ -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 + +#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_ diff --git a/src/rust/src/blake2b.rs b/src/rust/src/blake2b.rs new file mode 100644 index 000000000..d1168b718 --- /dev/null +++ b/src/rust/src/blake2b.rs @@ -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()); +} diff --git a/src/rust/src/rustzcash.rs b/src/rust/src/rustzcash.rs index 9ee34332e..cd58dd94d 100644 --- a/src/rust/src/rustzcash.rs +++ b/src/rust/src/rustzcash.rs @@ -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; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 7a8376eea..6f5cb12af 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -14,6 +14,8 @@ #include "script/script.h" #include "uint256.h" +#include + using namespace std; typedef vector 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) { diff --git a/src/test/equihash_tests.cpp b/src/test/equihash_tests.cpp index 5eb41a640..c6899dfe0 100644 --- a/src/test/equihash_tests.cpp +++ b/src/test/equihash_tests.cpp @@ -13,8 +13,6 @@ #include "test/test_bitcoin.h" #include "uint256.h" -#include "sodium.h" - #include "librustzcash.h" #include @@ -49,12 +47,12 @@ void PrintSolutions(std::stringstream &strm, std::set> sol #ifdef ENABLE_MINING void TestEquihashSolvers(unsigned int n, unsigned int k, const std::string &I, const arith_uint256 &nonce, const std::set> &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> ret; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 99fa0c989..d79333256 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -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); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 9e43f206a..362b6e035 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -163,7 +163,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector& 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& 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)> validBlock = diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 0e7be0839..5a3aaf1ac 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -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 + namespace libzcash { template @@ -207,7 +208,7 @@ uint256 JoinSplit::h_sig( const std::array& 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 block(randomSeed.begin(), randomSeed.end()); @@ -220,15 +221,10 @@ uint256 JoinSplit::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; } diff --git a/src/zcash/NoteEncryption.cpp b/src/zcash/NoteEncryption.cpp index c7f452d6c..b20259996 100644 --- a/src/zcash/NoteEncryption.cpp +++ b/src/zcash/NoteEncryption.cpp @@ -8,6 +8,8 @@ #include "prf.h" #include "librustzcash.h" +#include + #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 { diff --git a/src/zcash/address/sapling.cpp b/src/zcash/address/sapling.cpp index ac86d7897..30aa77348 100644 --- a/src/zcash/address/sapling.cpp +++ b/src/zcash/address/sapling.cpp @@ -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 diff --git a/src/zcash/address/zip32.cpp b/src/zcash/address/zip32.cpp index d30bf9ffe..188a33e84 100644 --- a/src/zcash/address/zip32.cpp +++ b/src/zcash/address/zip32.cpp @@ -11,12 +11,12 @@ #include "zcash/prf.h" #include -#include +#include -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(); - 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; diff --git a/src/zcash/prf.cpp b/src/zcash/prf.cpp index e575d562b..49c178e59 100644 --- a/src/zcash/prf.cpp +++ b/src/zcash/prf.cpp @@ -4,8 +4,9 @@ #include #include +#include -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 PRF_expand(const uint256& sk, unsigned char t) @@ -15,12 +16,12 @@ std::array 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 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) { diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index bfcdd21a6..f795fa680 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -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);