|
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