From 0f010f04452e15373b7c1b64524fbf1897add5ab Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 20 Nov 2012 14:23:10 -0800 Subject: [PATCH] Close a loophole where someone requests a large number of proofs of work while they're very easy and then has unlimited use of our system for several minutes because they can keep turning in the easy proofs of work, causing us to keep raising the proof of work level to insane levels. --- src/cpp/ripple/ProofOfWork.cpp | 42 +++++++++++++++++++++++++++------- src/cpp/ripple/ProofOfWork.h | 2 ++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp index 7243620597..c550a97497 100644 --- a/src/cpp/ripple/ProofOfWork.cpp +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -109,12 +109,9 @@ bool ProofOfWork::checkSolution(const uint256& solution) const return getSHA512Half(buf2) <= mTarget; } -ProofOfWorkGenerator::ProofOfWorkGenerator() : - mIterations(128), - mTarget("0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), - mLastDifficultyChange(time(NULL)), - mValidTime(180) +ProofOfWorkGenerator::ProofOfWorkGenerator() : mValidTime(180) { + setDifficulty(1); RAND_bytes(mSecret.begin(), mSecret.size()); } @@ -162,6 +159,8 @@ POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint2 time_t t = lexical_cast_s(fields[3]); time_t now = time(NULL); + int iterations = lexical_cast_s(fields[2]); + { boost::mutex::scoped_lock sl(mLock); if ((t * 4) > (now + mValidTime)) @@ -169,10 +168,15 @@ POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint2 cLog(lsDEBUG) << "PoW " << token << " has expired"; return powEXPIRED; } + + if (((iterations != mIterations) || (target != mTarget)) && getPowEntry(target, iterations) < (mPowEntry - 2)) + { // difficulty has increased more than two times since PoW requested + cLog(lsINFO) << "Difficulty has increased since PoW requested"; + return powTOOEASY; + } } - - ProofOfWork pow(token, lexical_cast_s(fields[2]), challenge, target); + ProofOfWork pow(token, iterations, challenge, target); if (!pow.checkSolution(solution)) { cLog(lsDEBUG) << "PoW " << token << " has a bad nonce"; @@ -181,7 +185,6 @@ POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint2 { boost::mutex::scoped_lock sl(mLock); -// if (...) return powTOOEASY; if (!mSolvedChallenges.insert(powMap_vt(now, challenge)).second) { cLog(lsDEBUG) << "PoW " << token << " has been reused"; @@ -208,6 +211,16 @@ void ProofOfWorkGenerator::sweep() } while(1); } +void ProofOfWorkGenerator::loadHigh() +{ + // WRITEME +} + +void ProofOfWorkGenerator::loadLow() +{ + // WRITEME +} + struct PowEntry { const char *target; @@ -256,6 +269,19 @@ PowEntry PowEntries[31] = { "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 77309411328, 8 MB }; +int ProofOfWorkGenerator::getPowEntry(const uint256& target, int iterations) +{ + for (int i = 0; i < 31; ++i) + if (PowEntries[i].iterations == iterations) + { + uint256 t; + t.SetHex(PowEntries[i].target); + if (t == target) + return i; + } + return -1; +} + void ProofOfWorkGenerator::setDifficulty(int i) { assert((i >= 0) && (i <= 30)); diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h index 3d88ffd197..7c77f86594 100644 --- a/src/cpp/ripple/ProofOfWork.h +++ b/src/cpp/ripple/ProofOfWork.h @@ -78,6 +78,8 @@ public: void loadHigh(); void loadLow(); void sweep(void); + + static int getPowEntry(const uint256& target, int iterations); }; #endif