Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-2022 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 : 2117 : SignatureCache::SignatureCache(const size_t max_size_bytes)
21 : : {
22 : 2117 : 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 : 2117 : static constexpr unsigned char PADDING_ECDSA[32] = {'E'};
28 : 2117 : static constexpr unsigned char PADDING_SCHNORR[32] = {'S'};
29 [ + - ]: 2117 : m_salted_hasher_ecdsa.Write(nonce.begin(), 32);
30 [ + - ]: 2117 : m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32);
31 [ + - ]: 2117 : m_salted_hasher_schnorr.Write(nonce.begin(), 32);
32 [ + - ]: 2117 : m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32);
33 : :
34 [ + - ]: 2117 : const auto [num_elems, approx_size_bytes] = setValid.setup_bytes(max_size_bytes);
35 [ + - ]: 2117 : LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n",
36 : : approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
37 : 2117 : }
38 : :
39 : 167 : void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const
40 : : {
41 : 167 : CSHA256 hasher = m_salted_hasher_ecdsa;
42 : 167 : hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin());
43 : 167 : }
44 : :
45 : 68 : void SignatureCache::ComputeEntrySchnorr(uint256& entry, const uint256& hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const
46 : : {
47 : 68 : CSHA256 hasher = m_salted_hasher_schnorr;
48 : 68 : hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin());
49 : 68 : }
50 : :
51 : 235 : bool SignatureCache::Get(const uint256& entry, const bool erase)
52 : : {
53 : 235 : std::shared_lock<std::shared_mutex> lock(cs_sigcache);
54 : 235 : return setValid.contains(entry, erase);
55 : 235 : }
56 : :
57 : 2 : void SignatureCache::Set(const uint256& entry)
58 : : {
59 : 2 : std::unique_lock<std::shared_mutex> lock(cs_sigcache);
60 [ + - ]: 2 : setValid.insert(entry);
61 : 2 : }
62 : :
63 : 167 : bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
64 : : {
65 : 167 : uint256 entry;
66 : 167 : m_signature_cache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey);
67 [ + - ]: 167 : if (m_signature_cache.Get(entry, !store))
68 : : return true;
69 [ + + ]: 167 : if (!TransactionSignatureChecker::VerifyECDSASignature(vchSig, pubkey, sighash))
70 : : return false;
71 [ + + ]: 4 : if (store)
72 : 2 : m_signature_cache.Set(entry);
73 : : return true;
74 : : }
75 : :
76 : 68 : bool CachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const
77 : : {
78 : 68 : uint256 entry;
79 : 68 : m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
80 [ + - ]: 68 : if (m_signature_cache.Get(entry, !store)) return true;
81 [ - + ]: 68 : if (!TransactionSignatureChecker::VerifySchnorrSignature(sig, pubkey, sighash)) return false;
82 [ # # ]: 0 : if (store) m_signature_cache.Set(entry);
83 : : return true;
84 : : }
|