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 : 1086 : SignatureCache::SignatureCache(const size_t max_size_bytes)
21 : : {
22 : 1086 : 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 : 1086 : static constexpr unsigned char PADDING_ECDSA[32] = {'E'};
28 : 1086 : static constexpr unsigned char PADDING_SCHNORR[32] = {'S'};
29 [ + - ]: 1086 : m_salted_hasher_ecdsa.Write(nonce.begin(), 32);
30 [ + - ]: 1086 : m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32);
31 [ + - ]: 1086 : m_salted_hasher_schnorr.Write(nonce.begin(), 32);
32 [ + - ]: 1086 : m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32);
33 : :
34 [ + - ]: 1086 : const auto [num_elems, approx_size_bytes] = setValid.setup_bytes(max_size_bytes);
35 [ + - ]: 1086 : 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 : 1086 : }
38 : :
39 : 114225 : void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const
40 : : {
41 : 114225 : CSHA256 hasher = m_salted_hasher_ecdsa;
42 : 114225 : hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin());
43 : 114225 : }
44 : :
45 : 8104 : void SignatureCache::ComputeEntrySchnorr(uint256& entry, const uint256& hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const
46 : : {
47 : 8104 : CSHA256 hasher = m_salted_hasher_schnorr;
48 : 8104 : hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin());
49 : 8104 : }
50 : :
51 : 122329 : bool SignatureCache::Get(const uint256& entry, const bool erase)
52 : : {
53 : 122329 : std::shared_lock<std::shared_mutex> lock(cs_sigcache);
54 : 122329 : return setValid.contains(entry, erase);
55 : 122329 : }
56 : :
57 : 8225 : void SignatureCache::Set(const uint256& entry)
58 : : {
59 : 8225 : std::unique_lock<std::shared_mutex> lock(cs_sigcache);
60 [ + - ]: 8225 : setValid.insert(entry);
61 : 8225 : }
62 : :
63 : 114225 : bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
64 : : {
65 : 114225 : uint256 entry;
66 : 114225 : m_signature_cache.ComputeEntryECDSA(entry, sighash, vchSig, pubkey);
67 [ + + ]: 114225 : if (m_signature_cache.Get(entry, !store))
68 : : return true;
69 [ + + ]: 63871 : if (!TransactionSignatureChecker::VerifyECDSASignature(vchSig, pubkey, sighash))
70 : : return false;
71 [ + + ]: 63400 : if (store)
72 : 7500 : m_signature_cache.Set(entry);
73 : : return true;
74 : : }
75 : :
76 : 8104 : bool CachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const
77 : : {
78 : 8104 : uint256 entry;
79 : 8104 : m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
80 [ + + ]: 8104 : if (m_signature_cache.Get(entry, !store)) return true;
81 [ + + ]: 5477 : if (!TransactionSignatureChecker::VerifySchnorrSignature(sig, pubkey, sighash)) return false;
82 [ + + ]: 5357 : if (store) m_signature_cache.Set(entry);
83 : : return true;
84 : : }
|