Changeset View
Changeset View
Standalone View
Standalone View
src/test/txvalidationcache_tests.cpp
Show First 20 Lines • Show All 425 Lines • ▼ Show 20 Lines | // TODO: add tests for remaining script flags | ||||
STANDARD_SCRIPT_VERIFY_FLAGS, true, true, | STANDARD_SCRIPT_VERIFY_FLAGS, true, true, | ||||
txdata, &scriptchecks)); | txdata, &scriptchecks)); | ||||
// Should get 2 script checks back -- caching is on a whole-transaction | // Should get 2 script checks back -- caching is on a whole-transaction | ||||
// basis. | // basis. | ||||
BOOST_CHECK_EQUAL(scriptchecks.size(), 2U); | BOOST_CHECK_EQUAL(scriptchecks.size(), 2U); | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(scriptcache_values) { | |||||
// Test insertion and querying of keys&values from the script cache. | |||||
// Define a couple of macros (handier than functions since errors will print | |||||
// out the correct line number) | |||||
#define CHECK_CACHE_HAS(key, expected_sigchecks) \ | |||||
{ \ | |||||
int nSigChecksRet = 0xdeaddead; \ | |||||
BOOST_CHECK(IsKeyInScriptCache(key, false, nSigChecksRet)); \ | |||||
BOOST_CHECK_EQUAL(nSigChecksRet, expected_sigchecks); \ | |||||
} | |||||
#define CHECK_CACHE_MISSING(key) \ | |||||
{ \ | |||||
int nSigChecksDummy; \ | |||||
BOOST_CHECK(!IsKeyInScriptCache(key, false, nSigChecksDummy)); \ | |||||
} | |||||
InitScriptExecutionCache(); | |||||
// construct four distinct keys from very slightly different data | |||||
CMutableTransaction tx1; | |||||
tx1.nVersion = 1; | |||||
CMutableTransaction tx2; | |||||
tx2.nVersion = 2; | |||||
uint32_t flagsA = 0x7fffffff; | |||||
uint32_t flagsB = 0xffffffff; | |||||
ScriptCacheKey key1A(CTransaction(tx1), flagsA); | |||||
ScriptCacheKey key1B(CTransaction(tx1), flagsB); | |||||
ScriptCacheKey key2A(CTransaction(tx2), flagsA); | |||||
ScriptCacheKey key2B(CTransaction(tx2), flagsB); | |||||
BOOST_CHECK(key1A == key1A); | |||||
BOOST_CHECK(!(key1A == key1B)); | |||||
BOOST_CHECK(!(key1A == key2A)); | |||||
BOOST_CHECK(!(key1A == key2B)); | |||||
BOOST_CHECK(key1B == key1B); | |||||
BOOST_CHECK(!(key1B == key2A)); | |||||
BOOST_CHECK(!(key1B == key2B)); | |||||
BOOST_CHECK(key2A == key2A); | |||||
BOOST_CHECK(!(key2A == key2B)); | |||||
BOOST_CHECK(key2B == key2B); | |||||
// key is not yet inserted | |||||
CHECK_CACHE_MISSING(key1A); | |||||
// add the key and check it worked | |||||
AddKeyInScriptCache(key1A, 42); | |||||
CHECK_CACHE_HAS(key1A, 42); | |||||
CHECK_CACHE_MISSING(key1B); | |||||
CHECK_CACHE_MISSING(key2A); | |||||
CHECK_CACHE_MISSING(key2B); | |||||
// 0 may be stored | |||||
AddKeyInScriptCache(key1B, 0); | |||||
// Calculate the most possible transaction sigchecks that can occur in a | |||||
// standard transaction, and make sure the cache can hold it. | |||||
// | |||||
// To be pessimistic, use consensus (MAX_TX_SIZE) instead of policy | |||||
// (MAX_STANDARD_TX_SIZE) since that particular policy limit is bypassed on | |||||
// testnet. | |||||
// | |||||
// Assume that a standardness rule limiting density to ~33 bytes/sigcheck is | |||||
// in place. | |||||
constexpr int max_standard_sigchecks = 1 + (MAX_TX_SIZE / 33); | |||||
AddKeyInScriptCache(key2A, max_standard_sigchecks); | |||||
// try adding an unstoreable value | |||||
BOOST_CHECK_THROW(AddKeyInScriptCache(key2B, -1), std::range_error); | |||||
BOOST_CHECK_THROW( | |||||
AddKeyInScriptCache(key2B, SCRIPT_CACHE_MAX_SIGCHECKS + 1), | |||||
std::range_error); | |||||
// read out values again | |||||
CHECK_CACHE_HAS(key1A, 42); | |||||
CHECK_CACHE_HAS(key1B, 0); | |||||
CHECK_CACHE_HAS(key2A, max_standard_sigchecks); | |||||
CHECK_CACHE_MISSING(key2B); | |||||
// we can insert the max | |||||
AddKeyInScriptCache(key2A, SCRIPT_CACHE_MAX_SIGCHECKS); | |||||
// try overwriting an existing entry with different value (should never | |||||
// happen in practice but see what happens) | |||||
AddKeyInScriptCache(key1A, 99); | |||||
// currently, no replacement is done | |||||
CHECK_CACHE_HAS(key1A, 42); | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |