Split and refactor ProofOfWork

This commit is contained in:
Vinnie Falco
2013-06-05 07:09:00 -07:00
parent 4d1bf35236
commit 38edcc8f0d
19 changed files with 356 additions and 305 deletions

View File

@@ -47,6 +47,7 @@ Application::Application ()
, mHashRouter (IHashRouter::New (IHashRouter::getDefaultHoldTime ()))
, mValidations (IValidations::New ())
, mUNL (IUniqueNodeList::New (mIOService))
, mProofOfWorkFactory (IProofOfWorkFactory::New ())
// VFALCO: End new stuff
// VFALCO: TODO replace all NULL with nullptr
, mRpcDB (NULL)

View File

@@ -12,12 +12,10 @@
#include "LedgerAcquire.h"
#include "TransactionMaster.h"
#include "Wallet.h"
#include "Peer.h"
#include "NetworkOPs.h"
#include "WSDoor.h"
#include "SNTPClient.h"
#include "RPCHandler.h"
#include "ProofOfWork.h"
#include "LoadManager.h"
#include "TransactionQueue.h"
#include "OrderBookDB.h"
@@ -31,6 +29,7 @@ class IHashRouter;
class ILoadFeeTrack;
class IValidations;
class IUniqueNodeList;
class IProofOfWorkFactory;
class RPCDoor;
class PeerDoor;
@@ -54,7 +53,6 @@ class Application
SLECache mSLECache;
SNTPClient mSNTPClient;
JobQueue mJobQueue;
ProofOfWorkGenerator mPOWGen;
LoadManager mLoadMgr;
TXQueue mTxnQueue;
OrderBookDB mOrderBookDB;
@@ -66,6 +64,7 @@ class Application
beast::ScopedPointer <IHashRouter> mHashRouter;
beast::ScopedPointer <IValidations> mValidations;
beast::ScopedPointer <IUniqueNodeList> mUNL;
beast::ScopedPointer <IProofOfWorkFactory> mProofOfWorkFactory;
// VFALCO: End Clean stuff
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mNetNodeDB, *mPathFindDB, *mHashNodeDB;
@@ -111,7 +110,6 @@ public:
HashedObjectStore& getHashedObjectStore() { return mHashedObjectStore; }
JobQueue& getJobQueue() { return mJobQueue; }
boost::recursive_mutex& getMasterLock() { return mMasterLock; }
ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
LoadManager& getLoadManager() { return mLoadMgr; }
TXQueue& getTxnQueue() { return mTxnQueue; }
PeerDoor& getPeerDoor() { return *mPeerDoor; }
@@ -123,6 +121,7 @@ public:
IFeeVote& getFeeVote() { return *mFeeVote; }
IHashRouter& getHashRouter() { return *mHashRouter; }
IValidations& getValidations() { return *mValidations; }
IProofOfWorkFactory& getProofOfWorkFactory() { return *mProofOfWorkFactory; }
// VFALCO: TODO, Move these to the .cpp
bool running() { return mTxnDB != NULL; } // VFALCO: TODO, replace with nullptr when beast is available

View File

@@ -8,7 +8,6 @@
#include <boost/algorithm/string.hpp>
#include <algorithm>
#include "Peer.h"
#include "PeerDoor.h"
#include "Application.h"

View File

@@ -6,8 +6,6 @@
#include <boost/asio/ssl.hpp>
#include <boost/thread/mutex.hpp>
#include "Peer.h"
//
// Access to the Ripple network.
//

View File

@@ -14,7 +14,6 @@
#include <boost/weak_ptr.hpp>
#include "Ledger.h"
#include "Peer.h"
// How long before we try again to acquire the same ledger
#ifndef LEDGER_REACQUIRE_INTERVAL

View File

@@ -11,7 +11,6 @@
#include "Transaction.h"
#include "LedgerAcquire.h"
#include "LedgerProposal.h"
#include "Peer.h"
#include "CanonicalTXSet.h"
#include "TransactionEngine.h"

View File

@@ -3,7 +3,6 @@
#include "Ledger.h"
#include "LedgerHistory.h"
#include "Peer.h"
#include "LedgerAcquire.h"
#include "Transaction.h"
#include "TransactionEngine.h"

View File

@@ -6,7 +6,6 @@
#include <boost/ref.hpp>
#include "Version.h"
#include "Peer.h"
#include "Application.h"
#include "SerializedTransaction.h"
@@ -1319,7 +1318,7 @@ void Peer::recvProofWork(ripple::TMProofWork& packet)
}
uint256 response;
memcpy(response.begin(), packet.response().data(), 256 / 8);
POWResult r = theApp->getPowGen().checkProof(packet.token(), response);
POWResult r = theApp->getProofOfWorkFactory().checkProof(packet.token(), response);
if (r == powOK)
{
// credit peer

View File

@@ -10,7 +10,6 @@
#include "Ledger.h"
#include "Transaction.h"
#include "ProofOfWork.h"
#include "LoadManager.h"
typedef std::pair<std::string,int> ipPort;

View File

@@ -4,8 +4,6 @@
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include "Peer.h"
/*
Handles incoming connections from other Peers
*/

View File

@@ -1,97 +0,0 @@
#ifndef PROOF_OF_WORK__H
#define PROOF_OF_WORK__H
#include <string>
#include <boost/thread/mutex.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
enum POWResult
{
powOK = 0,
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
};
bool powResultInfo(POWResult powCode, std::string& strToken, std::string& strHuman);
class ProofOfWork
{
public:
static const int sMaxDifficulty;
typedef boost::shared_ptr<ProofOfWork> pointer;
ProofOfWork(const std::string& token, int iterations, const uint256& challenge, const uint256& target) :
mToken(token), mChallenge(challenge), mTarget(target), mIterations(iterations)
{ ; }
ProofOfWork(const std::string& token);
bool isValid() const;
uint256 solve(int maxIterations = 2 * sMaxIterations) const;
bool checkSolution(const uint256& solution) const;
const std::string& getToken() const { return mToken; }
const uint256& getChallenge() const { return mChallenge; }
// approximate number of hashes needed to solve
static uint64 getDifficulty(const uint256& target, int iterations);
uint64 getDifficulty() const { return getDifficulty(mTarget, mIterations); }
static bool validateToken(const std::string& strToken);
private:
std::string mToken;
uint256 mChallenge;
uint256 mTarget;
int mIterations;
static const uint256 sMinTarget;
static const int sMaxIterations;
};
class ProofOfWorkGenerator
{
public:
typedef boost::bimap< boost::bimaps::multiset_of<time_t>, boost::bimaps::unordered_set_of<uint256> > powMap_t;
typedef powMap_t::value_type powMap_vt;
public:
ProofOfWorkGenerator();
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();
void sweep(void);
const uint256& getSecret() const { return mSecret; }
void setSecret(const uint256& secret) { mSecret = secret; }
static int getPowEntry(const uint256& target, int iterations);
private:
uint256 mSecret;
int mIterations;
uint256 mTarget;
time_t mLastDifficultyChange;
int mValidTime;
int mPowEntry;
powMap_t mSolvedChallenges;
boost::mutex mLock;
};
#endif
// vim:ts=4

View File

@@ -20,7 +20,6 @@
#include "NicknameState.h"
#include "Offer.h"
#include "PFRequest.h"
#include "ProofOfWork.h"
SETUP_LOG (RPCHandler)
@@ -889,7 +888,7 @@ Json::Value RPCHandler::doProofCreate(Json::Value jvRequest, int& cost, ScopedLo
if (jvRequest.isMember("difficulty") || jvRequest.isMember("secret"))
{
ProofOfWorkGenerator pgGen;
ProofOfWorkFactory pgGen;
if (jvRequest.isMember("difficulty"))
{
@@ -913,7 +912,7 @@ Json::Value RPCHandler::doProofCreate(Json::Value jvRequest, int& cost, ScopedLo
jvResult["token"] = pgGen.getProof().getToken();
jvResult["secret"] = pgGen.getSecret().GetHex();
} else {
jvResult["token"] = theApp->getPowGen().getProof().getToken();
jvResult["token"] = theApp->getProofOfWorkFactory().getProof().getToken();
}
return jvResult;
@@ -971,7 +970,7 @@ Json::Value RPCHandler::doProofVerify(Json::Value jvRequest, int& cost, ScopedLo
POWResult prResult;
if (jvRequest.isMember("difficulty") || jvRequest.isMember("secret"))
{
ProofOfWorkGenerator pgGen;
ProofOfWorkFactory pgGen;
if (jvRequest.isMember("difficulty"))
{
@@ -999,7 +998,7 @@ Json::Value RPCHandler::doProofVerify(Json::Value jvRequest, int& cost, ScopedLo
else
{
// XXX Proof should not be marked as used from this
prResult = theApp->getPowGen().checkProof(strToken, uSolution);
prResult = theApp->getProofOfWorkFactory().checkProof(strToken, uSolution);
}
std::string sToken;

View File

@@ -0,0 +1,54 @@
#ifndef RIPPLE_IPROOFOFWORKFACTORY_H
#define RIPPLE_IPROOFOFWORKFACTORY_H
enum POWResult
{
powOK = 0,
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
};
// VFALCO: TODO move this to the class as a static member and rename it
bool powResultInfo (POWResult powCode, std::string& strToken, std::string& strHuman);
class IProofOfWorkFactory
{
public:
typedef boost::bimap< boost::bimaps::multiset_of<time_t>, boost::bimaps::unordered_set_of<uint256> > powMap_t;
typedef powMap_t::value_type powMap_vt;
public:
static IProofOfWorkFactory* New ();
virtual ~IProofOfWorkFactory () { }
// VFALCO: TODO which members can be const?
virtual ProofOfWork getProof () = 0;
virtual POWResult checkProof (const std::string& token, const uint256& solution) = 0;
virtual uint64 getDifficulty() = 0;
virtual void setDifficulty (int i) = 0;
virtual void loadHigh () = 0;
virtual void loadLow () = 0;
virtual void sweep () = 0;
virtual const uint256& getSecret () const = 0;
virtual void setSecret (const uint256& secret) = 0;
public:
static int getPowEntry (const uint256& target, int iterations);
};
#endif
// vim:ts=4

View File

@@ -0,0 +1,172 @@
#include <string>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/regex.hpp>
#include <openssl/rand.h>
SETUP_LOG (ProofOfWork)
bool powResultInfo(POWResult powCode, std::string& strToken, std::string& strHuman)
{
static struct {
POWResult powCode;
const char* cpToken;
const char* cpHuman;
} powResultInfoA[] = {
{ powREUSED, "powREUSED", "Proof-of-work has already been used." },
{ powBADNONCE, "powBADNONCE", "The solution does not meet the required difficulty." },
{ powEXPIRED, "powEXPIRED", "Token is expired." },
{ powCORRUPT, "powCORRUPT", "Invalid token." },
{ powTOOEASY, "powTOOEASY", "Difficulty has increased since token was issued." },
{ powOK, "powOK", "Valid proof-of-work." },
};
int iIndex = NUMBER(powResultInfoA);
while (iIndex-- && powResultInfoA[iIndex].powCode != powCode)
;
if (iIndex >= 0)
{
strToken = powResultInfoA[iIndex].cpToken;
strHuman = powResultInfoA[iIndex].cpHuman;
}
return iIndex >= 0;
}
const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
const int ProofOfWork::sMaxIterations(1 << 23);
const int ProofOfWork::sMaxDifficulty(30);
ProofOfWork::ProofOfWork (const std::string& token,
int iterations,
const uint256& challenge,
const uint256& target)
: mToken (token)
, mChallenge (challenge)
, mTarget (target)
, mIterations (iterations)
{
}
ProofOfWork::ProofOfWork (const std::string& token)
{
std::vector<std::string> fields;
boost::split(fields, token, boost::algorithm::is_any_of("-"));
if (fields.size() != 5)
throw std::runtime_error("invalid token");
mToken = token;
mChallenge.SetHex(fields[0]);
mTarget.SetHex(fields[1]);
mIterations = lexical_cast_s<int>(fields[2]);
}
bool ProofOfWork::isValid() const
{
if ((mIterations <= sMaxIterations) && (mTarget >= sMinTarget))
return true;
WriteLog (lsWARNING, ProofOfWork) << "Invalid PoW: " << mIterations << ", " << mTarget;
return false;
}
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))
{
WriteLog (lsINFO, ProofOfWork) << "Iterations:" << iterations;
WriteLog (lsINFO, ProofOfWork) << "MaxIterat: " << sMaxIterations;
WriteLog (lsINFO, ProofOfWork) << "Target: " << target;
WriteLog (lsINFO, ProofOfWork) << "MinTarget: " << 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 / 8);
// Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty
const unsigned char *ptr = target.begin();
while (*ptr == 0)
{
difficulty *= 256;
++ptr;
}
difficulty = (difficulty * 256) / (*ptr + 1);
return difficulty;
}
static uint256 getSHA512Half(const std::vector<uint256>& vec)
{
return Serializer::getSHA512Half(vec.front().begin(), vec.size() * (256 / 8));
}
uint256 ProofOfWork::solve(int maxIterations) const
{
if (!isValid())
throw std::runtime_error("invalid proof of work target/iteration");
uint256 nonce;
RandomNumbers::getInstance ().fill (&nonce);
std::vector<uint256> buf2;
buf2.resize(mIterations);
std::vector<uint256> buf1;
buf1.resize(3);
buf1[0] = mChallenge;
while (maxIterations > 0)
{
buf1[1] = nonce;
buf1[2].zero();
for (int i = (mIterations - 1); i >= 0; --i)
{
buf1[2] = getSHA512Half(buf1);
buf2[i] = buf1[2];
}
if (getSHA512Half(buf2) <= mTarget)
return nonce;
++nonce;
--maxIterations;
}
return uint256();
}
bool ProofOfWork::checkSolution(const uint256& solution) const
{
if (mIterations > sMaxIterations)
return false;
std::vector<uint256> buf1;
buf1.push_back(mChallenge);
buf1.push_back(solution);
buf1.push_back(uint256());
std::vector<uint256> buf2;
buf2.resize(mIterations);
for (int i = (mIterations - 1); i >= 0; --i)
{
buf1[2] = getSHA512Half(buf1);
buf2[i] = buf1[2];
}
return getSHA512Half(buf2) <= mTarget;
}
bool ProofOfWork::validateToken(const std::string& strToken)
{
static boost::regex reToken("[[:xdigit:]]{64}-[[:xdigit:]]{64}-[[:digit:]]+-[[:digit:]]+-[[:xdigit:]]{64}");
boost::smatch smMatch;
return boost::regex_match(strToken, smMatch, reToken);
}
// vim:ts=4

View File

@@ -0,0 +1,48 @@
#ifndef RIPPLE_PROOFOFWORK_H
#define RIPPLE_PROOFOFWORK_H
class ProofOfWork
{
public:
static const int sMaxDifficulty;
typedef boost::shared_ptr <ProofOfWork> pointer;
ProofOfWork (const std::string& token,
int iterations,
const uint256& challenge,
const uint256& target);
explicit ProofOfWork (const std::string& token);
bool isValid() const;
uint256 solve(int maxIterations = 2 * sMaxIterations) const;
bool checkSolution(const uint256& solution) const;
const std::string& getToken() const { return mToken; }
const uint256& getChallenge() const { return mChallenge; }
uint64 getDifficulty() const
{
return getDifficulty(mTarget, mIterations);
}
// approximate number of hashes needed to solve
static uint64 getDifficulty (const uint256& target, int iterations);
static bool validateToken (const std::string& strToken);
private:
std::string mToken;
uint256 mChallenge;
uint256 mTarget;
int mIterations;
static const uint256 sMinTarget;
static const int sMaxIterations;
};
#endif
// vim:ts=4

View File

@@ -1,171 +1,44 @@
#include "ProofOfWork.h"
#include <string>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/regex.hpp>
#include <openssl/rand.h>
SETUP_LOG (ProofOfWork)
bool powResultInfo(POWResult powCode, std::string& strToken, std::string& strHuman)
class ProofOfWorkFactory : public IProofOfWorkFactory
{
static struct {
POWResult powCode;
const char* cpToken;
const char* cpHuman;
} powResultInfoA[] = {
{ powREUSED, "powREUSED", "Proof-of-work has already been used." },
{ powBADNONCE, "powBADNONCE", "The solution does not meet the required difficulty." },
{ powEXPIRED, "powEXPIRED", "Token is expired." },
{ powCORRUPT, "powCORRUPT", "Invalid token." },
{ powTOOEASY, "powTOOEASY", "Difficulty has increased since token was issued." },
public:
ProofOfWorkFactory ();
{ powOK, "powOK", "Valid proof-of-work." },
};
ProofOfWork getProof();
POWResult checkProof(const std::string& token, const uint256& solution);
uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); }
void setDifficulty(int i);
int iIndex = NUMBER(powResultInfoA);
void loadHigh();
void loadLow();
void sweep(void);
while (iIndex-- && powResultInfoA[iIndex].powCode != powCode)
;
const uint256& getSecret() const { return mSecret; }
void setSecret(const uint256& secret) { mSecret = secret; }
if (iIndex >= 0)
{
strToken = powResultInfoA[iIndex].cpToken;
strHuman = powResultInfoA[iIndex].cpHuman;
}
static int getPowEntry (const uint256& target, int iterations);
return iIndex >= 0;
}
private:
uint256 mSecret;
int mIterations;
uint256 mTarget;
time_t mLastDifficultyChange;
int mValidTime;
int mPowEntry;
const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
const int ProofOfWork::sMaxIterations(1 << 23);
const int ProofOfWork::sMaxDifficulty(30);
powMap_t mSolvedChallenges;
boost::mutex mLock;
};
ProofOfWork::ProofOfWork(const std::string& token)
{
std::vector<std::string> fields;
boost::split(fields, token, boost::algorithm::is_any_of("-"));
if (fields.size() != 5)
throw std::runtime_error("invalid token");
mToken = token;
mChallenge.SetHex(fields[0]);
mTarget.SetHex(fields[1]);
mIterations = lexical_cast_s<int>(fields[2]);
}
bool ProofOfWork::isValid() const
{
if ((mIterations <= sMaxIterations) && (mTarget >= sMinTarget))
return true;
WriteLog (lsWARNING, ProofOfWork) << "Invalid PoW: " << mIterations << ", " << mTarget;
return false;
}
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))
{
WriteLog (lsINFO, ProofOfWork) << "Iterations:" << iterations;
WriteLog (lsINFO, ProofOfWork) << "MaxIterat: " << sMaxIterations;
WriteLog (lsINFO, ProofOfWork) << "Target: " << target;
WriteLog (lsINFO, ProofOfWork) << "MinTarget: " << 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 / 8);
// Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty
const unsigned char *ptr = target.begin();
while (*ptr == 0)
{
difficulty *= 256;
++ptr;
}
difficulty = (difficulty * 256) / (*ptr + 1);
return difficulty;
}
static uint256 getSHA512Half(const std::vector<uint256>& vec)
{
return Serializer::getSHA512Half(vec.front().begin(), vec.size() * (256 / 8));
}
uint256 ProofOfWork::solve(int maxIterations) const
{
if (!isValid())
throw std::runtime_error("invalid proof of work target/iteration");
uint256 nonce;
RandomNumbers::getInstance ().fill (&nonce);
std::vector<uint256> buf2;
buf2.resize(mIterations);
std::vector<uint256> buf1;
buf1.resize(3);
buf1[0] = mChallenge;
while (maxIterations > 0)
{
buf1[1] = nonce;
buf1[2].zero();
for (int i = (mIterations - 1); i >= 0; --i)
{
buf1[2] = getSHA512Half(buf1);
buf2[i] = buf1[2];
}
if (getSHA512Half(buf2) <= mTarget)
return nonce;
++nonce;
--maxIterations;
}
return uint256();
}
bool ProofOfWork::checkSolution(const uint256& solution) const
{
if (mIterations > sMaxIterations)
return false;
std::vector<uint256> buf1;
buf1.push_back(mChallenge);
buf1.push_back(solution);
buf1.push_back(uint256());
std::vector<uint256> buf2;
buf2.resize(mIterations);
for (int i = (mIterations - 1); i >= 0; --i)
{
buf1[2] = getSHA512Half(buf1);
buf2[i] = buf1[2];
}
return getSHA512Half(buf2) <= mTarget;
}
bool ProofOfWork::validateToken(const std::string& strToken)
{
static boost::regex reToken("[[:xdigit:]]{64}-[[:xdigit:]]{64}-[[:digit:]]+-[[:digit:]]+-[[:xdigit:]]{64}");
boost::smatch smMatch;
return boost::regex_match(strToken, smMatch, reToken);
}
ProofOfWorkGenerator::ProofOfWorkGenerator() : mValidTime(180)
ProofOfWorkFactory::ProofOfWorkFactory() : mValidTime(180)
{
setDifficulty(1);
RandomNumbers::getInstance ().fillBytes (mSecret.begin(), mSecret.size());
}
ProofOfWork ProofOfWorkGenerator::getProof()
ProofOfWork ProofOfWorkFactory::getProof()
{
// challenge - target - iterations - time - validator
static boost::format f("%s-%s-%d-%d");
@@ -184,7 +57,7 @@ ProofOfWork ProofOfWorkGenerator::getProof()
return ProofOfWork(s, mIterations, challenge, mTarget);
}
POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint256& solution)
POWResult ProofOfWorkFactory::checkProof(const std::string& token, const uint256& solution)
{ // challenge - target - iterations - time - validator
std::vector<std::string> fields;
@@ -245,7 +118,7 @@ POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint2
return powOK;
}
void ProofOfWorkGenerator::sweep()
void ProofOfWorkFactory::sweep()
{
time_t expire = time(NULL) - mValidTime;
@@ -261,7 +134,7 @@ void ProofOfWorkGenerator::sweep()
} while(1);
}
void ProofOfWorkGenerator::loadHigh()
void ProofOfWorkFactory::loadHigh()
{
time_t now = time(NULL);
@@ -274,7 +147,7 @@ void ProofOfWorkGenerator::loadHigh()
mLastDifficultyChange = now;
}
void ProofOfWorkGenerator::loadLow()
void ProofOfWorkFactory::loadLow()
{
time_t now = time(NULL);
@@ -335,7 +208,7 @@ PowEntry PowEntries[ProofOfWork::sMaxDifficulty + 1] =
{ "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 77309411328, 8 MB
};
int ProofOfWorkGenerator::getPowEntry(const uint256& target, int iterations)
int ProofOfWorkFactory::getPowEntry(const uint256& target, int iterations)
{
for (int i = 0; i < 31; ++i)
if (PowEntries[i].iterations == iterations)
@@ -348,7 +221,7 @@ int ProofOfWorkGenerator::getPowEntry(const uint256& target, int iterations)
return -1;
}
void ProofOfWorkGenerator::setDifficulty(int i)
void ProofOfWorkFactory::setDifficulty(int i)
{
assert((i >= 0) && (i <= ProofOfWork::sMaxDifficulty));
time_t now = time(NULL);
@@ -360,11 +233,16 @@ void ProofOfWorkGenerator::setDifficulty(int i)
mLastDifficultyChange = now;
}
IProofOfWorkFactory* IProofOfWorkFactory::New ()
{
return new ProofOfWorkFactory;
}
BOOST_AUTO_TEST_SUITE(ProofOfWork_suite)
BOOST_AUTO_TEST_CASE( ProofOfWork_test )
{
ProofOfWorkGenerator gen;
ProofOfWorkFactory gen;
ProofOfWork pow = gen.getProof();
WriteLog (lsINFO, ProofOfWork) << "Estimated difficulty: " << pow.getDifficulty();
uint256 solution = pow.solve(16777216);