mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-11 01:26:10 +01:00
Move its ownership to the ChainstateManager class. Next to simplifying usage of the kernel library by no longer requiring manual setup of the cache prior to using validation code, it also slims down the amount of memory allocated by BasicTestingSetup. Use this opportunity to make SignatureCache RAII styled Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
84 lines
3.3 KiB
C++
84 lines
3.3 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2022 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 <script/sigcache.h>
|
|
|
|
#include <crypto/sha256.h>
|
|
#include <logging.h>
|
|
#include <pubkey.h>
|
|
#include <random.h>
|
|
#include <script/interpreter.h>
|
|
#include <span.h>
|
|
#include <uint256.h>
|
|
|
|
#include <mutex>
|
|
#include <shared_mutex>
|
|
#include <vector>
|
|
|
|
SignatureCache::SignatureCache(const size_t max_size_bytes)
|
|
{
|
|
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, and then pad with 'E' for ECDSA and
|
|
// 'S' for Schnorr (followed by 0 bytes).
|
|
static constexpr unsigned char PADDING_ECDSA[32] = {'E'};
|
|
static constexpr unsigned char PADDING_SCHNORR[32] = {'S'};
|
|
m_salted_hasher_ecdsa.Write(nonce.begin(), 32);
|
|
m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32);
|
|
m_salted_hasher_schnorr.Write(nonce.begin(), 32);
|
|
m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32);
|
|
|
|
const auto [num_elems, approx_size_bytes] = setValid.setup_bytes(max_size_bytes);
|
|
LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n",
|
|
approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
|
|
}
|
|
|
|
void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const
|
|
{
|
|
CSHA256 hasher = m_salted_hasher_ecdsa;
|
|
hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin());
|
|
}
|
|
|
|
void SignatureCache::ComputeEntrySchnorr(uint256& entry, const uint256& hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const
|
|
{
|
|
CSHA256 hasher = m_salted_hasher_schnorr;
|
|
hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin());
|
|
}
|
|
|
|
bool SignatureCache::Get(const uint256& entry, const bool erase)
|
|
{
|
|
std::shared_lock<std::shared_mutex> lock(cs_sigcache);
|
|
return setValid.contains(entry, erase);
|
|
}
|
|
|
|
void SignatureCache::Set(const uint256& entry)
|
|
{
|
|
std::unique_lock<std::shared_mutex> lock(cs_sigcache);
|
|
setValid.insert(entry);
|
|
}
|
|
|
|
bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
|
|
{
|
|
uint256 entry;
|
|
m_signature_cache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey);
|
|
if (m_signature_cache.Get(entry, !store))
|
|
return true;
|
|
if (!TransactionSignatureChecker::VerifyECDSASignature(vchSig, pubkey, sighash))
|
|
return false;
|
|
if (store)
|
|
m_signature_cache.Set(entry);
|
|
return true;
|
|
}
|
|
|
|
bool CachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const
|
|
{
|
|
uint256 entry;
|
|
m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
|
|
if (m_signature_cache.Get(entry, !store)) return true;
|
|
if (!TransactionSignatureChecker::VerifySchnorrSignature(sig, pubkey, sighash)) return false;
|
|
if (store) m_signature_cache.Set(entry);
|
|
return true;
|
|
}
|