Remove timing-based signature cache unit test
Two changes: First removes a unit test that fails in my development environment (OSX, compiled -g3 with clang). sipa says that's not terribly surprising; the CMutableTransaction change makes signing a little more expensive but verification quicker. The unit test timed sign+verify-uncached versus verify-cached-five-times. He also says the test will be invalid when libsec256kp1 is integrated (because validation is super-optimized over signing). core.h change fixes a compiler warning (clang -Wall : CMutableTransaction defined as struct, declared as class in script.h).
This commit is contained in:
parent
343feecf56
commit
a90689ff98
2 changed files with 1 additions and 88 deletions
|
@ -20,7 +20,7 @@
|
||||||
class CCoins;
|
class CCoins;
|
||||||
class CKeyStore;
|
class CKeyStore;
|
||||||
class CTransaction;
|
class CTransaction;
|
||||||
class CMutableTransaction;
|
struct CMutableTransaction;
|
||||||
|
|
||||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
||||||
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
|
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
|
||||||
|
|
|
@ -231,91 +231,4 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
||||||
BOOST_CHECK(mapOrphanTransactionsByPrev.empty());
|
BOOST_CHECK(mapOrphanTransactionsByPrev.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(DoS_checkSig)
|
|
||||||
{
|
|
||||||
// Test signature caching code (see key.cpp Verify() methods)
|
|
||||||
|
|
||||||
CKey key;
|
|
||||||
key.MakeNewKey(true);
|
|
||||||
CBasicKeyStore keystore;
|
|
||||||
keystore.AddKey(key);
|
|
||||||
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
|
|
||||||
|
|
||||||
// 100 orphan transactions:
|
|
||||||
static const int NPREV=100;
|
|
||||||
CMutableTransaction orphans[NPREV];
|
|
||||||
for (int i = 0; i < NPREV; i++)
|
|
||||||
{
|
|
||||||
CMutableTransaction& tx = orphans[i];
|
|
||||||
tx.vin.resize(1);
|
|
||||||
tx.vin[0].prevout.n = 0;
|
|
||||||
tx.vin[0].prevout.hash = GetRandHash();
|
|
||||||
tx.vin[0].scriptSig << OP_1;
|
|
||||||
tx.vout.resize(1);
|
|
||||||
tx.vout[0].nValue = 1*CENT;
|
|
||||||
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
|
|
||||||
|
|
||||||
AddOrphanTx(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a transaction that depends on orphans:
|
|
||||||
CMutableTransaction tx;
|
|
||||||
tx.vout.resize(1);
|
|
||||||
tx.vout[0].nValue = 1*CENT;
|
|
||||||
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
|
|
||||||
tx.vin.resize(NPREV);
|
|
||||||
for (unsigned int j = 0; j < tx.vin.size(); j++)
|
|
||||||
{
|
|
||||||
tx.vin[j].prevout.n = 0;
|
|
||||||
tx.vin[j].prevout.hash = orphans[j].GetHash();
|
|
||||||
}
|
|
||||||
// Creating signatures primes the cache:
|
|
||||||
boost::posix_time::ptime mst1 = boost::posix_time::microsec_clock::local_time();
|
|
||||||
for (unsigned int j = 0; j < tx.vin.size(); j++)
|
|
||||||
BOOST_CHECK(SignSignature(keystore, orphans[j], tx, j));
|
|
||||||
boost::posix_time::ptime mst2 = boost::posix_time::microsec_clock::local_time();
|
|
||||||
boost::posix_time::time_duration msdiff = mst2 - mst1;
|
|
||||||
long nOneValidate = msdiff.total_milliseconds();
|
|
||||||
if (fDebug) printf("DoS_Checksig sign: %ld\n", nOneValidate);
|
|
||||||
|
|
||||||
// ... now validating repeatedly should be quick:
|
|
||||||
// 2.8GHz machine, -g build: Sign takes ~760ms,
|
|
||||||
// uncached Verify takes ~250ms, cached Verify takes ~50ms
|
|
||||||
// (for 100 single-signature inputs)
|
|
||||||
mst1 = boost::posix_time::microsec_clock::local_time();
|
|
||||||
for (unsigned int i = 0; i < 5; i++)
|
|
||||||
for (unsigned int j = 0; j < tx.vin.size(); j++)
|
|
||||||
BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL));
|
|
||||||
mst2 = boost::posix_time::microsec_clock::local_time();
|
|
||||||
msdiff = mst2 - mst1;
|
|
||||||
long nManyValidate = msdiff.total_milliseconds();
|
|
||||||
if (fDebug) printf("DoS_Checksig five: %ld\n", nManyValidate);
|
|
||||||
|
|
||||||
BOOST_CHECK_MESSAGE(nManyValidate < nOneValidate, "Signature cache timing failed");
|
|
||||||
|
|
||||||
// Empty a signature, validation should fail:
|
|
||||||
CScript save = tx.vin[0].scriptSig;
|
|
||||||
tx.vin[0].scriptSig = CScript();
|
|
||||||
BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL));
|
|
||||||
tx.vin[0].scriptSig = save;
|
|
||||||
|
|
||||||
// Swap signatures, validation should fail:
|
|
||||||
std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig);
|
|
||||||
BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL));
|
|
||||||
BOOST_CHECK(!VerifySignature(CCoins(orphans[1], MEMPOOL_HEIGHT), tx, 1, flags, SIGHASH_ALL));
|
|
||||||
std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig);
|
|
||||||
|
|
||||||
// Exercise -maxsigcachesize code:
|
|
||||||
mapArgs["-maxsigcachesize"] = "10";
|
|
||||||
// Generate a new, different signature for vin[0] to trigger cache clear:
|
|
||||||
CScript oldSig = tx.vin[0].scriptSig;
|
|
||||||
BOOST_CHECK(SignSignature(keystore, orphans[0], tx, 0));
|
|
||||||
BOOST_CHECK(tx.vin[0].scriptSig != oldSig);
|
|
||||||
for (unsigned int j = 0; j < tx.vin.size(); j++)
|
|
||||||
BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL));
|
|
||||||
mapArgs.erase("-maxsigcachesize");
|
|
||||||
|
|
||||||
LimitOrphanTxSize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
Loading…
Reference in a new issue