diff --git a/src/Makefile.test.include b/src/Makefile.test.include index a63bfd271..3c5b22af1 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,200 +1,201 @@ # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. TESTS += test/test_bitcoin LOG_DRIVER = $(srcdir)/test/test-bitcoin-driver EXTRA_DIST += test/test-bitcoin-driver bin_PROGRAMS += test/test_bitcoin noinst_PROGRAMS += test/test_bitcoin_fuzzy TEST_SRCDIR = test TEST_BINARY=test/test_bitcoin$(EXEEXT) JSON_TEST_FILES = \ test/data/script_tests.json \ test/data/base58_keys_valid.json \ test/data/base58_encode_decode.json \ test/data/base58_keys_invalid.json \ test/data/tx_invalid.json \ test/data/tx_valid.json \ test/data/sighash.json RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) # test_bitcoin binary # BITCOIN_TESTS =\ test/scriptnum10.h \ test/activation_tests.cpp \ test/addrman_tests.cpp \ test/allocator_tests.cpp \ test/amount_tests.cpp \ test/arith_uint256_tests.cpp \ test/avalanche_tests.cpp \ test/base32_tests.cpp \ test/base58_tests.cpp \ test/base64_tests.cpp \ test/bip32_tests.cpp \ test/blockcheck_tests.cpp \ test/blockencodings_tests.cpp \ test/blockindex_tests.cpp \ test/blockstatus_tests.cpp \ test/bloom_tests.cpp \ test/bswap_tests.cpp \ test/cashaddr_tests.cpp \ test/cashaddrenc_tests.cpp \ test/checkdatasig_tests.cpp \ test/checkpoints_tests.cpp \ test/checkqueue_tests.cpp \ test/coins_tests.cpp \ test/compress_tests.cpp \ test/config_tests.cpp \ test/core_io_tests.cpp \ test/crypto_tests.cpp \ test/cuckoocache_tests.cpp \ test/dbwrapper_tests.cpp \ test/DoS_tests.cpp \ test/dstencode_tests.cpp \ test/excessiveblock_tests.cpp \ test/feerate_tests.cpp \ test/finalization_tests.cpp \ test/getarg_tests.cpp \ test/hash_tests.cpp \ test/inv_tests.cpp \ test/jsonutil.cpp \ test/jsonutil.h \ test/key_tests.cpp \ test/limitedmap_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ test/merkle_tests.cpp \ test/miner_tests.cpp \ test/monolith_opcodes.cpp \ test/multisig_tests.cpp \ test/net_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ test/prevector_tests.cpp \ test/radix_tests.cpp \ test/raii_event_tests.cpp \ test/random_tests.cpp \ test/rcu_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ test/rwcollection_tests.cpp \ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ test/script_commitment_tests.cpp \ test/script_P2SH_tests.cpp \ test/script_tests.cpp \ test/scriptflags.cpp \ test/scriptflags.h \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ + test/sigcache_tests.cpp \ test/sigencoding_tests.cpp \ test/sighash_tests.cpp \ test/sighashtype_tests.cpp \ test/sigopcount_tests.cpp \ test/sigutil.cpp \ test/sigutil.h \ test/skiplist_tests.cpp \ test/streams_tests.cpp \ test/sync_tests.cpp \ test/test_bitcoin.cpp \ test/test_bitcoin.h \ test/test_bitcoin_main.cpp \ test/timedata_tests.cpp \ test/transaction_tests.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ test/undo_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ test/validation_tests.cpp \ test/work_comparator_tests.cpp \ rpc/test/server_tests.cpp if ENABLE_WALLET BITCOIN_TESTS += \ wallet/test/wallet_test_fixture.cpp \ wallet/test/wallet_test_fixture.h \ wallet/test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ wallet/test/walletdb_tests.cpp \ wallet/test/crypto_tests.cpp endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) test_test_bitcoin_LDADD = if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ test_test_bitcoin_LDADD += $(ZMQ_LIBS) endif # # test_bitcoin_fuzzy binary # test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_test_bitcoin_fuzzy_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) $(BITCOIN_TESTS): $(GENERATED_TEST_FILES) CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) CLEANFILES += $(CLEAN_BITCOIN_TEST) bitcoin_test: $(TEST_BINARY) bitcoin_test_check: $(TEST_BINARY) FORCE $(MAKE) check-TESTS TESTS=$^ bitcoin_test_clean : FORCE rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY) check-local: @echo "Running test/util/bitcoin-util-test.py..." $(top_builddir)/test/util/bitcoin-util-test.py $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check if EMBEDDED_UNIVALUE $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check endif %.json.h: %.json @$(MKDIR_P) $(@D) @{ \ echo "namespace json_tests{" && \ echo "static unsigned const char $(*F)[] = {" && \ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \ echo "};};"; \ } > "$@.new" && mv -f "$@.new" "$@" @echo "Generated $@" diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 12fb7bae5..48c8c573f 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -1,99 +1,114 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "sigcache.h" #include "cuckoocache.h" #include "memusage.h" #include "pubkey.h" #include "random.h" #include "uint256.h" #include "util.h" #include namespace { /** * Valid signature cache, to avoid doing expensive ECDSA signature checking * twice for every transaction (once when accepted into memory pool, and * again when accepted into the block chain) */ class CSignatureCache { private: //! Entries are SHA256(nonce || signature hash || public key || signature): uint256 nonce; typedef CuckooCache::cache map_type; map_type setValid; boost::shared_mutex cs_sigcache; public: CSignatureCache() { GetRandBytes(nonce.begin(), 32); } void ComputeEntry(uint256 &entry, const uint256 &hash, const std::vector &vchSig, const CPubKey &pubkey) { CSHA256() .Write(nonce.begin(), 32) .Write(hash.begin(), 32) .Write(&pubkey[0], pubkey.size()) .Write(&vchSig[0], vchSig.size()) .Finalize(entry.begin()); } bool Get(const uint256 &entry, const bool erase) { boost::shared_lock lock(cs_sigcache); return setValid.contains(entry, erase); } void Set(uint256 &entry) { boost::unique_lock lock(cs_sigcache); setValid.insert(entry); } uint32_t setup_bytes(size_t n) { return setValid.setup_bytes(n); } }; /** * In previous versions of this code, signatureCache was a local static variable * in CachingTransactionSignatureChecker::VerifySignature. We initialize * signatureCache outside of VerifySignature to avoid the atomic operation per * call overhead associated with local static variables even though * signatureCache could be made local to VerifySignature. */ static CSignatureCache signatureCache; } // namespace // To be called once in AppInit2/TestingSetup to initialize the signatureCache void InitSignatureCache() { // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero, // setup_bytes creates the minimum possible cache (2 elements). size_t nMaxCacheSize = std::min(std::max(int64_t(0), gArgs.GetArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE)), MAX_MAX_SIG_CACHE_SIZE) * (size_t(1) << 20); size_t nElems = signatureCache.setup_bytes(nMaxCacheSize); LogPrintf("Using %zu MiB out of %zu requested for signature cache, able to " "store %zu elements\n", (nElems * sizeof(uint256)) >> 20, nMaxCacheSize >> 20, nElems); } -bool CachingTransactionSignatureChecker::VerifySignature( - const std::vector &vchSig, const CPubKey &pubkey, - const uint256 &sighash) const { +template +bool RunMemoizedCheck(const std::vector &vchSig, const CPubKey &pubkey, + const uint256 &sighash, bool storeOrErase, const F &fun) { uint256 entry; signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey); - if (signatureCache.Get(entry, !store)) { + if (signatureCache.Get(entry, !storeOrErase)) { return true; } - if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, - sighash)) { + if (!fun()) { return false; } - if (store) { + if (storeOrErase) { signatureCache.Set(entry); } return true; } + +bool CachingTransactionSignatureChecker::IsCached( + const std::vector &vchSig, const CPubKey &pubkey, + const uint256 &sighash) const { + return RunMemoizedCheck(vchSig, pubkey, sighash, true, + [] { return false; }); +} + +bool CachingTransactionSignatureChecker::VerifySignature( + const std::vector &vchSig, const CPubKey &pubkey, + const uint256 &sighash) const { + return RunMemoizedCheck(vchSig, pubkey, sighash, store, [&] { + return TransactionSignatureChecker::VerifySignature(vchSig, pubkey, + sighash); + }); +} diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 856952a0b..28b1123ea 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -1,61 +1,66 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_SCRIPT_SIGCACHE_H #define BITCOIN_SCRIPT_SIGCACHE_H #include "script/interpreter.h" #include // DoS prevention: limit cache size to 32MB (over 1000000 entries on 64-bit // systems). Due to how we count cache size, actual memory usage is slightly // more (~32.25 MB) static const unsigned int DEFAULT_MAX_SIG_CACHE_SIZE = 32; // Maximum sig cache size allowed static const int64_t MAX_MAX_SIG_CACHE_SIZE = 16384; class CPubKey; /** * We're hashing a nonce into the entries themselves, so we don't need extra * blinding in the set hash computation. * * This may exhibit platform endian dependent behavior but because these are * nonced hashes (random) and this state is only ever used locally it is safe. * All that matters is local consistency. */ class SignatureCacheHasher { public: template uint32_t operator()(const uint256 &key) const { static_assert(hash_select < 8, "SignatureCacheHasher only has 8 hashes available."); uint32_t u; std::memcpy(&u, key.begin() + 4 * hash_select, 4); return u; } }; class CachingTransactionSignatureChecker : public TransactionSignatureChecker { private: bool store; + bool IsCached(const std::vector &vchSig, const CPubKey &vchPubKey, + const uint256 &sighash) const; + public: CachingTransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn, bool storeIn, PrecomputedTransactionData &txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amountIn, txdataIn), store(storeIn) {} bool VerifySignature(const std::vector &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const override; + + friend class TestCachingTransactionSignatureChecker; }; void InitSignatureCache(); #endif // BITCOIN_SCRIPT_SIGCACHE_H diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 436f945de..4c54abb52 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,172 +1,173 @@ # Copyright (c) 2018 The Bitcoin developers project(bitcoin-test) # Process json files. file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/data") find_program(PYTHON python) function(gen_json_header NAME) set(HEADERS "") foreach(f ${ARGN}) set(h "${CMAKE_CURRENT_BINARY_DIR}/${f}.h") # Get the proper name for the test variable. get_filename_component(TEST_NAME ${f} NAME_WE) add_custom_command(OUTPUT ${h} COMMAND ${PYTHON} ARGS "${CMAKE_CURRENT_SOURCE_DIR}/data/generate_header.py" "${TEST_NAME}" "${CMAKE_CURRENT_SOURCE_DIR}/${f}" > ${h} MAIN_DEPENDENCY ${f} DEPENDS "data/generate_header.py" VERBATIM ) list(APPEND HEADERS ${h}) endforeach(f) set(${NAME} "${HEADERS}" PARENT_SCOPE) endfunction() gen_json_header(JSON_HEADERS data/script_tests.json data/base58_keys_valid.json data/base58_encode_decode.json data/base58_keys_invalid.json data/tx_invalid.json data/tx_valid.json data/sighash.json ) include(TestSuite) create_test_suite(bitcoin) add_dependencies(check check-bitcoin) add_test_to_suite(bitcoin test_bitcoin activation_tests.cpp addrman_tests.cpp allocator_tests.cpp amount_tests.cpp arith_uint256_tests.cpp avalanche_tests.cpp base32_tests.cpp base58_tests.cpp base64_tests.cpp bip32_tests.cpp blockcheck_tests.cpp blockencodings_tests.cpp blockindex_tests.cpp blockstatus_tests.cpp bloom_tests.cpp bswap_tests.cpp cashaddr_tests.cpp cashaddrenc_tests.cpp checkdatasig_tests.cpp checkpoints_tests.cpp checkqueue_tests.cpp coins_tests.cpp compress_tests.cpp config_tests.cpp core_io_tests.cpp crypto_tests.cpp cuckoocache_tests.cpp dbwrapper_tests.cpp DoS_tests.cpp dstencode_tests.cpp excessiveblock_tests.cpp feerate_tests.cpp finalization_tests.cpp getarg_tests.cpp hash_tests.cpp inv_tests.cpp jsonutil.cpp key_tests.cpp limitedmap_tests.cpp main_tests.cpp mempool_tests.cpp merkle_tests.cpp miner_tests.cpp monolith_opcodes.cpp multisig_tests.cpp net_tests.cpp netbase_tests.cpp pmt_tests.cpp policyestimator_tests.cpp pow_tests.cpp prevector_tests.cpp radix_tests.cpp raii_event_tests.cpp random_tests.cpp rcu_tests.cpp reverselock_tests.cpp rpc_tests.cpp rwcollection_tests.cpp sanity_tests.cpp scheduler_tests.cpp script_commitment_tests.cpp script_P2SH_tests.cpp script_tests.cpp scriptflags.cpp scriptnum_tests.cpp serialize_tests.cpp + sigcache_tests.cpp sigencoding_tests.cpp sighash_tests.cpp sighashtype_tests.cpp sigopcount_tests.cpp sigutil.cpp skiplist_tests.cpp streams_tests.cpp sync_tests.cpp test_bitcoin.cpp test_bitcoin_main.cpp timedata_tests.cpp transaction_tests.cpp txvalidationcache_tests.cpp versionbits_tests.cpp uint256_tests.cpp undo_tests.cpp univalue_tests.cpp util_tests.cpp validation_tests.cpp work_comparator_tests.cpp # RPC Tests ../rpc/test/server_tests.cpp # Tests generated from JSON ${JSON_HEADERS} ) target_include_directories(test_bitcoin PUBLIC # To access the generated json headers. ${CMAKE_CURRENT_BINARY_DIR} ) find_package(Boost 1.58 REQUIRED unit_test_framework) target_link_libraries(test_bitcoin Boost::unit_test_framework rpcclient server) # We need to detect if the BOOST_TEST_DYN_LINK flag is required. set(CMAKE_REQUIRED_LIBRARIES Boost::unit_test_framework) check_cxx_source_compiles(" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include " BOOST_TEST_DYN_LINK) if(BOOST_TEST_DYN_LINK) target_compile_definitions(test_bitcoin PRIVATE BOOST_TEST_DYN_LINK) endif(BOOST_TEST_DYN_LINK) if(BUILD_BITCOIN_WALLET) target_sources(test_bitcoin PRIVATE ../wallet/test/wallet_test_fixture.cpp ../wallet/test/accounting_tests.cpp ../wallet/test/wallet_tests.cpp ../wallet/test/walletdb_tests.cpp ../wallet/test/crypto_tests.cpp ) endif() diff --git a/src/test/sigcache_tests.cpp b/src/test/sigcache_tests.cpp new file mode 100644 index 000000000..e0d0334dd --- /dev/null +++ b/src/test/sigcache_tests.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2012-2015 The Bitcoin Core developers +// Copyright (c) 2019- The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// (based on key_tests.cpp) + +#include "script/sigcache.h" + +#include "base58.h" +#include "dstencode.h" +#include "key.h" +#include "test/test_bitcoin.h" +#include "utilstrencodings.h" + +#include + +#include +#include + +static const std::string strSecret1 = + "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"; +static const std::string strSecret1C = + "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"; + +class TestCachingTransactionSignatureChecker { + /** + * Sigcache is only accessible via CachingTransactionSignatureChecker + */ + CachingTransactionSignatureChecker *pchecker; + +public: + TestCachingTransactionSignatureChecker( + CachingTransactionSignatureChecker &checkerarg) { + pchecker = &checkerarg; + } + + inline bool VerifyAndStore(const std::vector &vchSig, + const CPubKey &pubkey, const uint256 &sighash) { + return pchecker->VerifySignature(vchSig, pubkey, sighash); + } + + inline bool IsCached(const std::vector &vchSig, + const CPubKey &pubkey, const uint256 &sighash) { + return pchecker->IsCached(vchSig, pubkey, sighash); + } +}; + +BOOST_FIXTURE_TEST_SUITE(sigcache_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(test1) { + /** + * Making CachingTransactionSignatureChecke requires a tx. So we make a + * dummy transaction (doesn't matter what it is) to construct it. + */ + CDataStream stream( + ParseHex( + "010000000122739e70fbee987a8be1788395a2f2e6ad18ccb7ff611cd798071539" + "dde3c38e000000000151ffffffff010000000000000000016a00000000"), + SER_NETWORK, PROTOCOL_VERSION); + CTransaction dummyTx(deserialize, stream); + PrecomputedTransactionData txdata(dummyTx); + CachingTransactionSignatureChecker checker(&dummyTx, 0, 0 * SATOSHI, true, + txdata); + + TestCachingTransactionSignatureChecker testChecker(checker); + + CBitcoinSecret bsecret1, bsecret1C; + BOOST_CHECK(bsecret1.SetString(strSecret1)); + BOOST_CHECK(bsecret1C.SetString(strSecret1C)); + + CKey key1 = bsecret1.GetKey(); + BOOST_CHECK(key1.IsCompressed() == false); + CKey key1C = bsecret1C.GetKey(); + BOOST_CHECK(key1C.IsCompressed() == true); + + CPubKey pubkey1 = key1.GetPubKey(); + CPubKey pubkey1C = key1C.GetPubKey(); + + for (int n = 0; n < 16; n++) { + std::string strMsg = strprintf("Sigcache test1 %i: xx", n); + uint256 hashMsg = Hash(strMsg.begin(), strMsg.end()); + uint256 hashMsg2 = Hash(strMsg.begin() + 1, strMsg.end()); + + std::vector sig; + BOOST_CHECK(key1.SignECDSA(hashMsg, sig)); + std::vector sig2; + BOOST_CHECK(key1.SignECDSA(hashMsg2, sig2)); + + // cross-check + BOOST_CHECK(!testChecker.VerifyAndStore(sig2, pubkey1, hashMsg)); + BOOST_CHECK(!testChecker.VerifyAndStore(sig, pubkey1, hashMsg2)); + // that should not have put them in cache... + BOOST_CHECK(!testChecker.IsCached(sig2, pubkey1, hashMsg)); + BOOST_CHECK(!testChecker.IsCached(sig, pubkey1, hashMsg2)); + + // check that it's not in cache at start + BOOST_CHECK(!testChecker.IsCached(sig, pubkey1, hashMsg)); + BOOST_CHECK(!testChecker.IsCached(sig2, pubkey1, hashMsg2)); + // Insert into cache + BOOST_CHECK(testChecker.VerifyAndStore(sig, pubkey1, hashMsg)); + BOOST_CHECK(testChecker.VerifyAndStore(sig2, pubkey1, hashMsg2)); + // check that it's in + BOOST_CHECK(testChecker.IsCached(sig, pubkey1, hashMsg)); + BOOST_CHECK(testChecker.IsCached(sig2, pubkey1, hashMsg2)); + // check that different signature hits different entry + BOOST_CHECK(!testChecker.IsCached(sig2, pubkey1, hashMsg)); + // check that compressed pubkey hits different entry + BOOST_CHECK(!testChecker.IsCached(sig, pubkey1C, hashMsg)); + // check that different message hits different entry + BOOST_CHECK(!testChecker.IsCached(sig, pubkey1, hashMsg2)); + + // compressed key is for same privkey, so verifying works: + BOOST_CHECK(testChecker.VerifyAndStore(sig, pubkey1C, hashMsg)); + // now we *should* get a hit + BOOST_CHECK(testChecker.IsCached(sig, pubkey1C, hashMsg)); + } +} + +BOOST_AUTO_TEST_SUITE_END()