More PoW work.

This commit is contained in:
JoelKatz
2012-11-13 03:41:39 -08:00
parent 210170a2cb
commit ee0b63d19e
2 changed files with 73 additions and 5 deletions

View File

@@ -3,7 +3,7 @@
#include <string>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <openssl/rand.h>
@@ -134,6 +134,60 @@ ProofOfWork ProofOfWorkGenerator::getProof()
return ProofOfWork(s, mIterations, challenge, mTarget);
}
POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint256& solution)
{ // challenge - target - iterations - time - validator
std::vector<std::string> fields;
boost::split(fields, token, boost::algorithm::is_any_of("-"));
if (fields.size() != 5)
{
cLog(lsDEBUG) << "PoW " << token << " is corrupt";
return powCORRUPT;
}
std::string v = mSecret.GetHex() + fields[0] + "-" + fields[1] + "-" + fields[2] + "-" + fields[3];
if (fields[4] != Serializer::getSHA512Half(v).GetHex())
{
cLog(lsDEBUG) << "PoW " << token << " has a bad token";
return powBADTOKEN;
}
uint256 challenge, target;
challenge.SetHex(fields[0]);
target.SetHex(fields[1]);
time_t t = lexical_cast_s<time_t>(fields[3]);
time_t now = time(NULL);
{
boost::mutex::scoped_lock sl(mLock);
if ((t * 4) > (now + mValidTime))
{
cLog(lsDEBUG) << "PoW " << token << " has expired";
return powEXPIRED;
}
}
ProofOfWork pow(token, lexical_cast_s<int>(fields[2]), challenge, target);
if (!pow.checkSolution(solution))
{
cLog(lsDEBUG) << "PoW " << token << " has a bad nonce";
return powBADNONCE;
}
{
boost::mutex::scoped_lock sl(mLock);
if (!mSolvedChallenges.insert(powMap_vt(now, challenge)).second)
{
cLog(lsDEBUG) << "PoW " << token << " has been reused";
return powREUSED;
}
}
return powOK;
}
BOOST_AUTO_TEST_SUITE(ProofOfWork_suite)
BOOST_AUTO_TEST_CASE( ProofOfWork_test )
@@ -146,6 +200,15 @@ BOOST_AUTO_TEST_CASE( ProofOfWork_test )
BOOST_FAIL("Unable to solve proof of work");
if (!pow.checkSolution(solution))
BOOST_FAIL("Solution did not check");
cLog(lsDEBUG) << "A bad nonce error is expected";
if (gen.checkProof(pow.getToken(), uint256()) != powBADNONCE)
BOOST_FAIL("Empty solution didn't show bad nonce");
if (gen.checkProof(pow.getToken(), solution) != powOK)
BOOST_FAIL("Solution did not check with issuer");
cLog(lsDEBUG) << "A reused nonce error is expected";
if (gen.checkProof(pow.getToken(), solution) != powREUSED)
BOOST_FAIL("Reuse solution not detected");
}
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -5,7 +5,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
#include "uint256.h"
@@ -17,6 +17,7 @@ enum POWResult
powBADNONCE = 2,
powBADTOKEN = 3,
powEXPIRED = 4,
powCORRUPT = 5,
};
class ProofOfWork
@@ -41,6 +42,9 @@ public:
uint256 solve(int maxIterations) 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); }
@@ -49,7 +53,7 @@ public:
class ProofOfWorkGenerator
{
public:
typedef boost::bimap< boost::bimaps::multiset_of<time_t>, boost::bimaps::set_of<uint256> > powMap_t;
typedef boost::bimap< boost::bimaps::multiset_of<time_t>, boost::bimaps::unordered_set_of<uint256> > powMap_t;
typedef powMap_t::value_type powMap_vt;
protected:
@@ -66,11 +70,12 @@ public:
ProofOfWorkGenerator();
ProofOfWork getProof();
bool checkProof(const std::string& token, const uint256& solution);
POWResult checkProof(const std::string& token, const uint256& solution);
uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); }
void loadHigh();
void loadLow();
uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); }
void sweep(void);
};
#endif