diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -51,6 +51,7 @@ duplicate_inputs.cpp examples.cpp gcs_filter.cpp + hashpadding.cpp lockedpool.cpp mempool_eviction.cpp mempool_stress.cpp diff --git a/src/bench/hashpadding.cpp b/src/bench/hashpadding.cpp new file mode 100644 --- /dev/null +++ b/src/bench/hashpadding.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2015-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include + +static void PrePadded(benchmark::State &state) { + CSHA256 hasher; + + // Setup the salted hasher + uint256 nonce = GetRandHash(); + hasher.Write(nonce.begin(), 32); + hasher.Write(nonce.begin(), 32); + uint256 data = GetRandHash(); + while (state.KeepRunning()) { + uint8_t out[32]; + CSHA256 h = hasher; + h.Write(data.begin(), 32); + h.Finalize(out); + } +} + +BENCHMARK(PrePadded, 10000); + +static void RegularPadded(benchmark::State &state) { + CSHA256 hasher; + + // Setup the salted hasher + uint256 nonce = GetRandHash(); + uint256 data = GetRandHash(); + while (state.KeepRunning()) { + uint8_t out[32]; + CSHA256 h = hasher; + h.Write(nonce.begin(), 32); + h.Write(data.begin(), 32); + h.Finalize(out); + } +} + +BENCHMARK(RegularPadded, 10000); diff --git a/src/script/scriptcache.cpp b/src/script/scriptcache.cpp --- a/src/script/scriptcache.cpp +++ b/src/script/scriptcache.cpp @@ -70,10 +70,17 @@ }; static CuckooCache::cache - scriptExecutionCache; -static uint256 scriptExecutionCacheNonce(GetRandHash()); + g_scriptExecutionCache; +static CSHA256 g_scriptExecutionCacheHasher; void InitScriptExecutionCache() { + // Setup the salted hasher + uint256 nonce = GetRandHash(); + // We want the nonce to be 64 bytes long to force the hasher to process + // this chunk, which makes later hash computations more efficient. We + // just write our 32-byte entropy twice to fill the 64 bytes. + g_scriptExecutionCacheHasher.Write(nonce.begin(), 32); + g_scriptExecutionCacheHasher.Write(nonce.begin(), 32); // nMaxCacheSize is unsigned. If -maxscriptcachesize is set to zero, // setup_bytes creates the minimum possible cache (2 elements). size_t nMaxCacheSize = @@ -82,7 +89,7 @@ DEFAULT_MAX_SCRIPT_CACHE_SIZE)), MAX_MAX_SCRIPT_CACHE_SIZE) * (size_t(1) << 20); - size_t nElems = scriptExecutionCache.setup_bytes(nMaxCacheSize); + size_t nElems = g_scriptExecutionCache.setup_bytes(nMaxCacheSize); LogPrintf("Using %zu MiB out of %zu requested for script execution cache, " "able to store %zu elements\n", (nElems * sizeof(uint256)) >> 20, nMaxCacheSize >> 20, nElems); @@ -90,13 +97,8 @@ ScriptCacheKey::ScriptCacheKey(const CTransaction &tx, uint32_t flags) { std::array hash; - // We only use the first 19 bytes of nonce to avoid a second SHA round - - // giving us 19 + 32 + 4 = 55 bytes (+ 8 + 1 = 64) - static_assert(55 - sizeof(flags) - 32 >= 128 / 8, - "Want at least 128 bits of nonce for script execution cache"); - CSHA256() - .Write(scriptExecutionCacheNonce.begin(), 55 - sizeof(flags) - 32) - .Write(tx.GetHash().begin(), 32) + CSHA256 hasher = g_scriptExecutionCacheHasher; + hasher.Write(tx.GetHash().begin(), 32) .Write((uint8_t *)&flags, sizeof(flags)) .Finalize(hash.begin()); @@ -110,7 +112,7 @@ AssertLockHeld(cs_main); ScriptCacheElement elem(key, 0); - bool ret = scriptExecutionCache.get(elem, erase); + bool ret = g_scriptExecutionCache.get(elem, erase); nSigChecksOut = elem.nSigChecks; return ret; } @@ -121,5 +123,5 @@ AssertLockHeld(cs_main); ScriptCacheElement elem(key, nSigChecks); - scriptExecutionCache.insert(elem); + g_scriptExecutionCache.insert(elem); } diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -23,7 +23,7 @@ class CSignatureCache { private: //! Entries are SHA256(nonce || signature hash || public key || signature): - uint256 nonce; + CSHA256 m_salted_hasher; typedef CuckooCache::cache, SignatureCacheHasher> map_type; @@ -31,14 +31,20 @@ boost::shared_mutex cs_sigcache; public: - CSignatureCache() { GetRandBytes(nonce.begin(), 32); } + CSignatureCache() { + uint256 nonce = GetRandHash(); + // We want the nonce to be 64 bytes long to force the hasher to process + // this chunk, which makes later hash computations more efficient. We + // just write our 32-byte entropy twice to fill the 64 bytes. + m_salted_hasher.Write(nonce.begin(), 32); + m_salted_hasher.Write(nonce.begin(), 32); + } void ComputeEntry(uint256 &entry, const uint256 &hash, const std::vector &vchSig, const CPubKey &pubkey) { - CSHA256() - .Write(nonce.begin(), 32) - .Write(hash.begin(), 32) + CSHA256 hasher = m_salted_hasher; + hasher.Write(hash.begin(), 32) .Write(&pubkey[0], pubkey.size()) .Write(&vchSig[0], vchSig.size()) .Finalize(entry.begin());