From 645f7022c45bff68b4dda61039d2db42435dd1d3 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 19 Nov 2012 01:06:23 -0800 Subject: [PATCH] More PoW work. --- src/cpp/ripple/ProofOfWork.cpp | 104 +++++++++++++++++++++++++++++++-- src/cpp/ripple/ProofOfWork.h | 12 ++-- 2 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp index 8d8d50b69..0aba3820b 100644 --- a/src/cpp/ripple/ProofOfWork.cpp +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -18,7 +18,10 @@ const int ProofOfWork::sMaxIterations(1 << 23); bool ProofOfWork::isValid() const { - return ((mIterations <= sMaxIterations) && (mTarget >= sMinTarget)); + if ((mIterations <= sMaxIterations) && (mTarget >= sMinTarget)) + return true; + cLog(lsWARNING) << "Invalid PoW: " << mIterations << ", " << mTarget; + return false; } uint64 ProofOfWork::getDifficulty(const uint256& target, int iterations) @@ -33,7 +36,7 @@ uint64 ProofOfWork::getDifficulty(const uint256& target, int iterations) } // more iterations means more hashes per iteration but also a larger final hash - uint64 difficulty = iterations + (iterations / 4); + uint64 difficulty = iterations + (iterations / 8); // Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty const unsigned char *ptr = target.begin(); @@ -70,7 +73,7 @@ uint256 ProofOfWork::solve(int maxIterations) const while (maxIterations > 0) { buf1[1] = nonce; - buf1[2] = uint256(); + buf1[2].zero(); for (int i = (mIterations - 1); i >= 0; --i) { buf1[2] = getSHA512Half(buf1); @@ -149,7 +152,7 @@ POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint2 if (fields[4] != Serializer::getSHA512Half(v).GetHex()) { cLog(lsDEBUG) << "PoW " << token << " has a bad token"; - return powBADTOKEN; + return powCORRUPT; } uint256 challenge, target; @@ -178,6 +181,7 @@ 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"; @@ -188,6 +192,77 @@ POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint2 return powOK; } +void ProofOfWorkGenerator::sweep() +{ + time_t expire = time(NULL) - mValidTime; + + boost::mutex::scoped_lock sl(mLock); + do + { + powMap_t::left_map::iterator it = mSolvedChallenges.left.begin(); + if (it == mSolvedChallenges.left.end()) + return; + if (it->first >= expire) + return; + mSolvedChallenges.left.erase(it); + } while(1); +} + +struct PowEntry +{ + const char *target; + int iterations; +}; + +PowEntry PowEntries[32] = +{ + // FIXME: These targets are too low and iteration counts too low + // These get too difficulty before they become sufficently RAM intensive + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 256 }, // Hashes:5242880 KB=8 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 512 }, // Hashes:5242880 KB=16 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 512 }, // Hashes:10485760 KB=16 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 1024 }, // Hashes:10485760 KB=32 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 1024 }, // Hashes:20971520 KB=32 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2048 }, // Hashes:20971520 KB=64 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2048 }, // Hashes:41943040 KB=64 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 4096 }, // Hashes:41943040 KB=128 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 4096 }, // Hashes:83886080 KB=128 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 8192 }, // Hashes:83886080 KB=256 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 8192 }, // Hashes:167772160 KB=256 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16384 }, // Hashes:167772160 KB=512 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 32768 }, // Hashes:335544320 MB=1 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 32768 }, // Hashes:671088640 MB=1 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 65536 }, // Hashes:671088640 MB=2 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 65536 }, // Hashes:1342177280 MB=2 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 131072 }, // Hashes:1342177280 MB=4 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 131072 }, // Hashes:2684354560 MB=4 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144 }, // Hashes:2684354560 MB=8 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 524288 }, // Hashes:5368709120 MB=16 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 524288 }, // Hashes:10737418240 MB=16 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 1048576 }, // Hashes:10737418240 MB=32 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 1048576 }, // Hashes:21474836480 MB=32 + { "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2097152 }, // Hashes:21474836480 MB=64 + { "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2097152 }, // Hashes:42949672960 MB=64 + { "00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 524288 }, // Hashes:85899345920 MB=16 + { "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 524288 }, // Hashes:171798691840 MB=16 + { "00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 1048576 }, // Hashes:171798691840 MB=32 + { "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 1048576 }, // Hashes:343597383680 MB=32 + { "00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2097152 }, // Hashes:343597383680 MB=64 + { "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 2097152 }, // Hashes:687194767360 MB=64 +}; + +void ProofOfWorkGenerator::setDifficulty(int i) +{ + assert((i >= 0) && (i <= 31)); + time_t now = time(NULL); + + boost::mutex::scoped_lock sl(mLock); + mPowEntry = i; + mIterations = PowEntries[i].iterations; + mTarget.SetHex(PowEntries[i].target); + mLastDifficultyChange = now; +} + BOOST_AUTO_TEST_SUITE(ProofOfWork_suite) BOOST_AUTO_TEST_CASE( ProofOfWork_test ) @@ -209,6 +284,27 @@ BOOST_AUTO_TEST_CASE( ProofOfWork_test ) cLog(lsDEBUG) << "A reused nonce error is expected"; if (gen.checkProof(pow.getToken(), solution) != powREUSED) BOOST_FAIL("Reuse solution not detected"); + +#ifdef SOLVE_POWS + for (int i = 0; i < 12; ++i) + { + gen.setDifficulty(i); + ProofOfWork pow = gen.getProof(); + cLog(lsINFO) << "Level: " << i << ", Estimated difficulty: " << pow.getDifficulty(); + uint256 solution = pow.solve(131072); + if (solution.isZero()) + cLog(lsINFO) << "Giving up"; + else + { + cLog(lsINFO) << "Solution found"; + if (gen.checkProof(pow.getToken(), solution) != powOK) + { + cLog(lsFATAL) << "Solution fails"; + } + } +#endif + + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h index a09eec737..3d88ffd19 100644 --- a/src/cpp/ripple/ProofOfWork.h +++ b/src/cpp/ripple/ProofOfWork.h @@ -13,11 +13,11 @@ enum POWResult { powOK = 0, - powREUSED = 1, - powBADNONCE = 2, - powBADTOKEN = 3, - powEXPIRED = 4, - powCORRUPT = 5, + powREUSED = 1, // already submitted + powBADNONCE = 2, // you didn't solve it + powEXPIRED = 3, // time is up + powCORRUPT = 4, + powTOOEASY = 5, // the difficulty increased too much while you solved it }; class ProofOfWork @@ -62,6 +62,7 @@ protected: uint256 mTarget; time_t mLastDifficultyChange; int mValidTime; + int mPowEntry; powMap_t mSolvedChallenges; boost::mutex mLock; @@ -72,6 +73,7 @@ public: ProofOfWork getProof(); POWResult checkProof(const std::string& token, const uint256& solution); uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); } + void setDifficulty(int i); void loadHigh(); void loadLow();