From 3613c45962f0ae222d219f2e7ff2e5f11be7ecdb Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 10 Nov 2012 22:19:03 -0800 Subject: [PATCH] Start coding proof of work logic. --- src/cpp/ripple/ProofOfWork.cpp | 66 ++++++++++++++++++++++++++++++++++ src/cpp/ripple/ProofOfWork.h | 66 ++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/cpp/ripple/ProofOfWork.cpp create mode 100644 src/cpp/ripple/ProofOfWork.h diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp new file mode 100644 index 0000000000..9ccb29eb25 --- /dev/null +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -0,0 +1,66 @@ +#include "ProofOfWork.h" + +#include + +#include + +#include "Serializer.h" + +const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); +const int ProofOfWork::sMaxIterations(1 << 23); + +bool ProofOfWork::isValid() const +{ + return ((mIterations <= sMaxIterations) && (mTarget >= sMinTarget)); +} + +uint64 ProofOfWork::getDifficulty(const uint256& target, int iterations) +{ // calculate the approximate number of hashes required to solve this proof of work + if ((iterations > sMaxIterations) || (target < sMinTarget)); + throw std::runtime_error("invalid proof of work target/iteration"); + + // more iterations means more hashes per iteration but also a larger final hash + uint64 difficulty = iterations * (iterations / 4 + 1); + + // Multiply the number of hashes needed by 16 for each leading zero in the hex difficulty + const unsigned char *ptr = target.begin(); + while (*ptr == 0) + { + difficulty *= 16; + ptr++; + } + + // If the first digit after a zero isn't an F, multiply + difficulty *= (16 - *ptr); + + return difficulty; +} + +uint256 ProofOfWork::solve(int maxIterations) const +{ + if (!isValid()) + throw std::runtime_error("invalid proof of work target/iteration"); + + uint256 nonce; + RAND_bytes(nonce.begin(), nonce.size()); + + Serializer s1, s2; + std::vector buf; + buf.reserve((256 / 8) * mIterations); + + while (maxIterations > 8) + { + s1.add256(mChallenge); + s1.add256(nonce); +// uint256 base = s1.getSHA512Half(); + + for (int i = 0; i < mIterations; ++i) + { + // WRITEME + } + + s1.erase(); + nonce++; + } + return uint256(); +} diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h new file mode 100644 index 0000000000..1391be91c3 --- /dev/null +++ b/src/cpp/ripple/ProofOfWork.h @@ -0,0 +1,66 @@ +#ifndef PROOF_OF_WORK__H +#define PROOF_OF_WORK__H + +#include + +#include +#include +#include +#include + +#include "uint256.h" + +class ProofOfWork +{ +protected: + + std::string mToken; + uint256 mChallenge; + uint256 mTarget; + int mIterations; + + static const uint256 sMinTarget; + static const int sMaxIterations; + +public: + ProofOfWork(const std::string& token, int iterations, const uint256& challenge, const uint256& target) : + mToken(token), mChallenge(challenge), mTarget(target), mIterations(iterations) + { ; } + + bool isValid() const; + + uint256 solve(int maxIterations) const; + bool checkSolution(const uint256& solution) const; + + // approximate number of hashes needed to solve + static uint64 getDifficulty(const uint256& target, int iterations); + uint64 getDifficulty() const { return getDifficulty(mTarget, mIterations); } +}; + +class ProofOfWorkGenerator +{ +public: + typedef boost::bimap< boost::bimaps::multiset_of, boost::bimaps::set_of > powMap_t; + typedef powMap_t::value_type powMap_vt; + +protected: + uint256 mSecret; + int mIterations; + uint256 mTarget; + time_t mLastDifficultyChange; + + powMap_t mSolvedChallenges; + boost::mutex mLock; + +public: + ProofOfWorkGenerator(const uint256& secret); + + ProofOfWork getProof(); + bool checkProof(const std::string& token, const uint256& solution); + + void loadHigh(); + void loadLow(); + uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); } +}; + +#endif