|
5 | 5 |
|
6 | 6 | #include <script/sigcache.h> |
7 | 7 |
|
8 | | -#include <common/system.h> |
| 8 | +#include <crypto/sha256.h> |
9 | 9 | #include <logging.h> |
10 | 10 | #include <pubkey.h> |
11 | 11 | #include <random.h> |
| 12 | +#include <script/interpreter.h> |
| 13 | +#include <span.h> |
12 | 14 | #include <uint256.h> |
13 | 15 |
|
14 | | -#include <cuckoocache.h> |
15 | | - |
16 | | -#include <algorithm> |
17 | 16 | #include <mutex> |
18 | 17 | #include <shared_mutex> |
19 | 18 | #include <vector> |
20 | 19 |
|
21 | | -namespace { |
22 | | -/** |
23 | | - * Valid signature cache, to avoid doing expensive ECDSA signature checking |
24 | | - * twice for every transaction (once when accepted into memory pool, and |
25 | | - * again when accepted into the block chain) |
26 | | - */ |
27 | | -class CSignatureCache |
| 20 | +SignatureCache::SignatureCache() |
28 | 21 | { |
29 | | -private: |
30 | | - //! Entries are SHA256(nonce || 'E' or 'S' || 31 zero bytes || signature hash || public key || signature): |
31 | | - CSHA256 m_salted_hasher_ecdsa; |
32 | | - CSHA256 m_salted_hasher_schnorr; |
33 | | - typedef CuckooCache::cache<uint256, SignatureCacheHasher> map_type; |
34 | | - map_type setValid; |
35 | | - std::shared_mutex cs_sigcache; |
| 22 | + 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 | + static constexpr unsigned char PADDING_ECDSA[32] = {'E'}; |
| 28 | + static constexpr unsigned char PADDING_SCHNORR[32] = {'S'}; |
| 29 | + m_salted_hasher_ecdsa.Write(nonce.begin(), 32); |
| 30 | + m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32); |
| 31 | + m_salted_hasher_schnorr.Write(nonce.begin(), 32); |
| 32 | + m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32); |
| 33 | +} |
36 | 34 |
|
37 | | -public: |
38 | | - CSignatureCache() |
39 | | - { |
40 | | - uint256 nonce = GetRandHash(); |
41 | | - // We want the nonce to be 64 bytes long to force the hasher to process |
42 | | - // this chunk, which makes later hash computations more efficient. We |
43 | | - // just write our 32-byte entropy, and then pad with 'E' for ECDSA and |
44 | | - // 'S' for Schnorr (followed by 0 bytes). |
45 | | - static constexpr unsigned char PADDING_ECDSA[32] = {'E'}; |
46 | | - static constexpr unsigned char PADDING_SCHNORR[32] = {'S'}; |
47 | | - m_salted_hasher_ecdsa.Write(nonce.begin(), 32); |
48 | | - m_salted_hasher_ecdsa.Write(PADDING_ECDSA, 32); |
49 | | - m_salted_hasher_schnorr.Write(nonce.begin(), 32); |
50 | | - m_salted_hasher_schnorr.Write(PADDING_SCHNORR, 32); |
51 | | - } |
| 35 | +void SignatureCache::ComputeEntryECDSA(uint256& entry, const uint256& hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const |
| 36 | +{ |
| 37 | + CSHA256 hasher = m_salted_hasher_ecdsa; |
| 38 | + hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin()); |
| 39 | +} |
52 | 40 |
|
53 | | - void |
54 | | - ComputeEntryECDSA(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const |
55 | | - { |
56 | | - CSHA256 hasher = m_salted_hasher_ecdsa; |
57 | | - hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin()); |
58 | | - } |
| 41 | +void SignatureCache::ComputeEntrySchnorr(uint256& entry, const uint256& hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const |
| 42 | +{ |
| 43 | + CSHA256 hasher = m_salted_hasher_schnorr; |
| 44 | + hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin()); |
| 45 | +} |
59 | 46 |
|
60 | | - void |
61 | | - ComputeEntrySchnorr(uint256& entry, const uint256 &hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const |
62 | | - { |
63 | | - CSHA256 hasher = m_salted_hasher_schnorr; |
64 | | - hasher.Write(hash.begin(), 32).Write(pubkey.data(), pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin()); |
65 | | - } |
| 47 | +bool SignatureCache::Get(const uint256& entry, const bool erase) |
| 48 | +{ |
| 49 | + std::shared_lock<std::shared_mutex> lock(cs_sigcache); |
| 50 | + return setValid.contains(entry, erase); |
| 51 | +} |
66 | 52 |
|
67 | | - bool |
68 | | - Get(const uint256& entry, const bool erase) |
69 | | - { |
70 | | - std::shared_lock<std::shared_mutex> lock(cs_sigcache); |
71 | | - return setValid.contains(entry, erase); |
72 | | - } |
| 53 | +void SignatureCache::Set(const uint256& entry) |
| 54 | +{ |
| 55 | + std::unique_lock<std::shared_mutex> lock(cs_sigcache); |
| 56 | + setValid.insert(entry); |
| 57 | +} |
73 | 58 |
|
74 | | - void Set(const uint256& entry) |
75 | | - { |
76 | | - std::unique_lock<std::shared_mutex> lock(cs_sigcache); |
77 | | - setValid.insert(entry); |
78 | | - } |
79 | | - std::pair<uint32_t, size_t> setup_bytes(size_t n) |
80 | | - { |
81 | | - return setValid.setup_bytes(n); |
82 | | - } |
83 | | -}; |
| 59 | +std::pair<uint32_t, size_t> SignatureCache::setup_bytes(size_t n) |
| 60 | +{ |
| 61 | + return setValid.setup_bytes(n); |
| 62 | +} |
84 | 63 |
|
85 | 64 | /* In previous versions of this code, signatureCache was a local static variable |
86 | 65 | * in CachingTransactionSignatureChecker::VerifySignature. We initialize |
87 | 66 | * signatureCache outside of VerifySignature to avoid the atomic operation per |
88 | 67 | * call overhead associated with local static variables even though |
89 | 68 | * signatureCache could be made local to VerifySignature. |
90 | 69 | */ |
91 | | -static CSignatureCache signatureCache; |
92 | | -} // namespace |
| 70 | +static SignatureCache signatureCache; |
93 | 71 |
|
94 | 72 | // To be called once in AppInitMain/BasicTestingSetup to initialize the |
95 | 73 | // signatureCache. |
|
0 commit comments