/root/bitcoin/src/script/sigcache.cpp
Line | Count | Source |
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 | 0 | { |
22 | 0 | 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 | 0 | static constexpr unsigned char PADDING_ECDSA[32] = {'E'}; |
28 | 0 | static constexpr unsigned char PADDING_SCHNORR[32] = {'S'}; |
29 | 0 | m_salted_hasher_ecdsa.Write(nonce.begin(), 32); |
30 | 0 | m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32); |
31 | 0 | m_salted_hasher_schnorr.Write(nonce.begin(), 32); |
32 | 0 | m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32); |
33 | |
|
34 | 0 | const auto [num_elems, approx_size_bytes] = setValid.setup_bytes(max_size_bytes); |
35 | 0 | LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n", |
36 | 0 | approx_size_bytes >> 20, max_size_bytes >> 20, num_elems); |
37 | 0 | } |
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 | } |