/Users/eugenesiegel/btc/bitcoin/src/script/sigcache.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2009-2010 Satoshi Nakamoto | 
| 2 |  | // Copyright (c) 2009-present The Bitcoin Core developers | 
| 3 |  | // Distributed under the MIT software license, see the accompanying | 
| 4 |  | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | 
| 5 |  |  | 
| 6 |  | #include <script/sigcache.h> | 
| 7 |  |  | 
| 8 |  | #include <crypto/sha256.h> | 
| 9 |  | #include <logging.h> | 
| 10 |  | #include <pubkey.h> | 
| 11 |  | #include <random.h> | 
| 12 |  | #include <script/interpreter.h> | 
| 13 |  | #include <span.h> | 
| 14 |  | #include <uint256.h> | 
| 15 |  |  | 
| 16 |  | #include <mutex> | 
| 17 |  | #include <shared_mutex> | 
| 18 |  | #include <vector> | 
| 19 |  |  | 
| 20 |  | SignatureCache::SignatureCache(const size_t max_size_bytes) | 
| 21 | 51.2k | { | 
| 22 | 51.2k |     uint256 nonce = GetRandHash(); | 
| 23 |  |     // We want the nonce to be 64 bytes long to force the hasher to process | 
| 24 |  |     // this chunk, which makes later hash computations more efficient. We | 
| 25 |  |     // just write our 32-byte entropy, and then pad with 'E' for ECDSA and | 
| 26 |  |     // 'S' for Schnorr (followed by 0 bytes). | 
| 27 | 51.2k |     static constexpr unsigned char PADDING_ECDSA[32] = {'E'}; | 
| 28 | 51.2k |     static constexpr unsigned char PADDING_SCHNORR[32] = {'S'}; | 
| 29 | 51.2k |     m_salted_hasher_ecdsa.Write(nonce.begin(), 32); | 
| 30 | 51.2k |     m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32); | 
| 31 | 51.2k |     m_salted_hasher_schnorr.Write(nonce.begin(), 32); | 
| 32 | 51.2k |     m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32); | 
| 33 |  |  | 
| 34 | 51.2k |     const auto [num_elems, approx_size_bytes] = setValid.setup_bytes(max_size_bytes); | 
| 35 | 51.2k |     LogInfo("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements",| Line | Count | Source |  | 356 | 51.2k | #define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__) | Line | Count | Source |  | 350 | 51.2k | #define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__) | 
 | 
 | 
| 36 | 51.2k |               approx_size_bytes >> 20, max_size_bytes >> 20, num_elems); | 
| 37 | 51.2k | } | 
| 38 |  |  | 
| 39 |  | void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const | 
| 40 | 0 | { | 
| 41 | 0 |     CSHA256 hasher = m_salted_hasher_ecdsa; | 
| 42 | 0 |     hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin()); | 
| 43 | 0 | } | 
| 44 |  |  | 
| 45 |  | void SignatureCache::ComputeEntrySchnorr(uint256& entry, const uint256& hash, std::span<const unsigned char> sig, const XOnlyPubKey& pubkey) const | 
| 46 | 0 | { | 
| 47 | 0 |     CSHA256 hasher = m_salted_hasher_schnorr; | 
| 48 | 0 |     hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin()); | 
| 49 | 0 | } | 
| 50 |  |  | 
| 51 |  | bool SignatureCache::Get(const uint256& entry, const bool erase) | 
| 52 | 0 | { | 
| 53 | 0 |     std::shared_lock<std::shared_mutex> lock(cs_sigcache); | 
| 54 | 0 |     return setValid.contains(entry, erase); | 
| 55 | 0 | } | 
| 56 |  |  | 
| 57 |  | void SignatureCache::Set(const uint256& entry) | 
| 58 | 0 | { | 
| 59 | 0 |     std::unique_lock<std::shared_mutex> lock(cs_sigcache); | 
| 60 | 0 |     setValid.insert(entry); | 
| 61 | 0 | } | 
| 62 |  |  | 
| 63 |  | bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const | 
| 64 | 0 | { | 
| 65 | 0 |     uint256 entry; | 
| 66 | 0 |     m_signature_cache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey); | 
| 67 | 0 |     if (m_signature_cache.Get(entry, !store)) | 
| 68 | 0 |         return true; | 
| 69 | 0 |     if (!TransactionSignatureChecker::VerifyECDSASignature(vchSig, pubkey, sighash)) | 
| 70 | 0 |         return false; | 
| 71 | 0 |     if (store) | 
| 72 | 0 |         m_signature_cache.Set(entry); | 
| 73 | 0 |     return true; | 
| 74 | 0 | } | 
| 75 |  |  | 
| 76 |  | bool CachingTransactionSignatureChecker::VerifySchnorrSignature(std::span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const | 
| 77 | 0 | { | 
| 78 | 0 |     uint256 entry; | 
| 79 | 0 |     m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey); | 
| 80 | 0 |     if (m_signature_cache.Get(entry, !store)) return true; | 
| 81 | 0 |     if (!TransactionSignatureChecker::VerifySchnorrSignature(sig, pubkey, sighash)) return false; | 
| 82 | 0 |     if (store) m_signature_cache.Set(entry); | 
| 83 | 0 |     return true; | 
| 84 | 0 | } |