From 5c7a92ba764502c6f15cad1ba99c833ab76b379a Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Sat, 11 May 2013 09:39:44 +0200 Subject: [PATCH 1/9] RPC: Add proof_create. --- src/cpp/ripple/CallRPC.cpp | 12 ++++++++++++ src/cpp/ripple/CallRPC.h | 1 + src/cpp/ripple/ProofOfWork.cpp | 5 +++-- src/cpp/ripple/ProofOfWork.h | 5 +++++ src/cpp/ripple/RPCHandler.cpp | 34 ++++++++++++++++++++++++++++++++++ src/cpp/ripple/RPCHandler.h | 1 + 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index 268cda5725..f28eb397f1 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -471,6 +471,17 @@ Json::Value RPCParser::parseAccountRaw(const Json::Value& jvParams, bool bPeer) return jvRequest; } +// proof_create [] +Json::Value RPCParser::parseProofCreate(const Json::Value& jvParams) +{ + Json::Value jvRequest; + + if (1 == jvParams.size()) + jvRequest["difficulty"] = jvParams[0u].asInt(); + + return jvRequest; +} + // ripple_path_find [] Json::Value RPCParser::parseRipplePathFind(const Json::Value& jvParams) { @@ -698,6 +709,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) { "peers", &RPCParser::parseAsIs, 0, 0 }, { "ping", &RPCParser::parseAsIs, 0, 0 }, // { "profile", &RPCParser::parseProfile, 1, 9 }, + { "proof_create", &RPCParser::parseProofCreate, 0, 1 }, { "random", &RPCParser::parseAsIs, 0, 0 }, { "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 }, { "sign", &RPCParser::parseSignSubmit, 2, 2 }, diff --git a/src/cpp/ripple/CallRPC.h b/src/cpp/ripple/CallRPC.h index ac726afdf9..6fa8f27252 100644 --- a/src/cpp/ripple/CallRPC.h +++ b/src/cpp/ripple/CallRPC.h @@ -34,6 +34,7 @@ protected: #endif Json::Value parseLogLevel(const Json::Value& jvParams); Json::Value parseOwnerInfo(const Json::Value& jvParams); + Json::Value parseProofCreate(const Json::Value& jvParams); Json::Value parseRandom(const Json::Value& jvParams); Json::Value parseRipplePathFind(const Json::Value& jvParams); Json::Value parseSMS(const Json::Value& jvParams); diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp index 7ec6a8ef91..2036a66f67 100644 --- a/src/cpp/ripple/ProofOfWork.cpp +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -15,6 +15,7 @@ SETUP_LOG(); const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); const int ProofOfWork::sMaxIterations(1 << 23); +const int ProofOfWork::sMaxDifficulty(30); bool ProofOfWork::isValid() const { @@ -243,7 +244,7 @@ struct PowEntry int iterations; }; -PowEntry PowEntries[31] = +PowEntry PowEntries[ProofOfWork::sMaxDifficulty + 1] = { // target iterations hashes memory { "0CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 65536 }, // 1451874, 2 MB { "0CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 98304 }, // 2177811, 3 MB @@ -300,7 +301,7 @@ int ProofOfWorkGenerator::getPowEntry(const uint256& target, int iterations) void ProofOfWorkGenerator::setDifficulty(int i) { - assert((i >= 0) && (i <= 30)); + assert((i >= 0) && (i <= ProofOfWork::sMaxDifficulty)); time_t now = time(NULL); boost::mutex::scoped_lock sl(mLock); diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h index 0e1409c05b..1133a4c29f 100644 --- a/src/cpp/ripple/ProofOfWork.h +++ b/src/cpp/ripple/ProofOfWork.h @@ -20,6 +20,7 @@ enum POWResult powTOOEASY = 5, // the difficulty increased too much while you solved it }; + class ProofOfWork { protected: @@ -33,6 +34,8 @@ protected: static const int sMaxIterations; public: + static const int sMaxDifficulty; + typedef boost::shared_ptr pointer; ProofOfWork(const std::string& token, int iterations, const uint256& challenge, const uint256& target) : @@ -81,6 +84,8 @@ public: void loadLow(); void sweep(void); + const uint256& getSecret() const { return mSecret; } + static int getPowEntry(const uint256& target, int iterations); }; diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index f3aa3aee94..cab60568c8 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -23,6 +23,7 @@ #include "InstanceCounter.h" #include "Offer.h" #include "PFRequest.h" +#include "ProofOfWork.h" SETUP_LOG(); @@ -877,6 +878,38 @@ Json::Value RPCHandler::doProfile(Json::Value jvRequest, int& cost, ScopedLock& return obj; } +// { +// difficulty: // optional, if set, a temporary generator is +// // instantiated and its secret included +// } +Json::Value RPCHandler::doProofCreate(Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder) +{ + // XXX: Add ability to create proof with arbitrary secret and time + + Json::Value jvResult(Json::objectValue); + + if (jvRequest.isMember("difficulty")) + { + if (!jvRequest["difficulty"].isIntegral()) + return rpcError(rpcINVALID_PARAMS); + + int iDifficulty = jvRequest["difficulty"].asInt(); + + if (iDifficulty < 0 || iDifficulty > ProofOfWork::sMaxDifficulty) + return rpcError(rpcINVALID_PARAMS); + + ProofOfWorkGenerator pgGen; + pgGen.setDifficulty(iDifficulty); + + jvResult["token"] = pgGen.getProof().getToken(); + jvResult["secret"] = pgGen.getSecret().GetHex(); + } else { + jvResult["token"] = theApp->getPowGen().getProof().getToken(); + } + + return jvResult; +} + // { // account: || // account_index: // optional, defaults to 0. @@ -3343,6 +3376,7 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole, int & { "path_find", &RPCHandler::doPathFind, false, optCurrent }, { "ping", &RPCHandler::doPing, false, optNone }, // { "profile", &RPCHandler::doProfile, false, optCurrent }, + { "proof_create", &RPCHandler::doProofCreate, false, optNone }, { "random", &RPCHandler::doRandom, false, optNone }, { "ripple_path_find", &RPCHandler::doRipplePathFind, false, optCurrent }, { "sign", &RPCHandler::doSign, false, optCurrent }, diff --git a/src/cpp/ripple/RPCHandler.h b/src/cpp/ripple/RPCHandler.h index f5b73c39be..d90610f919 100644 --- a/src/cpp/ripple/RPCHandler.h +++ b/src/cpp/ripple/RPCHandler.h @@ -72,6 +72,7 @@ class RPCHandler Json::Value doPathFind(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doPing(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doProfile(Json::Value params, int& cost, ScopedLock& mlh); + Json::Value doProofCreate(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doRandom(Json::Value jvRequest, int& cost, ScopedLock& mlh); Json::Value doRipplePathFind(Json::Value jvRequest, int& cost, ScopedLock& mlh); Json::Value doServerInfo(Json::Value params, int& cost, ScopedLock& mlh); // for humans From c3d2eae667d63b62fe6044f5958720b55dbd0dd3 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Sun, 12 May 2013 11:39:46 +0200 Subject: [PATCH 2/9] RPC: Add proof_verify. --- src/cpp/ripple/CallRPC.cpp | 12 ++++++++++++ src/cpp/ripple/CallRPC.h | 1 + src/cpp/ripple/ProofOfWork.cpp | 31 +++++++++++++++++++++++++++++ src/cpp/ripple/ProofOfWork.h | 1 + src/cpp/ripple/RPCHandler.cpp | 36 ++++++++++++++++++++++++++++++++++ src/cpp/ripple/RPCHandler.h | 1 + 6 files changed, 82 insertions(+) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index f28eb397f1..86e5f15378 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -482,6 +482,17 @@ Json::Value RPCParser::parseProofCreate(const Json::Value& jvParams) return jvRequest; } +// proof_verify +Json::Value RPCParser::parseProofVerify(const Json::Value& jvParams) +{ + Json::Value jvRequest; + + jvRequest["token"] = jvParams[0u].asString(); + jvRequest["solution"] = jvParams[1u].asString(); + + return jvRequest; +} + // ripple_path_find [] Json::Value RPCParser::parseRipplePathFind(const Json::Value& jvParams) { @@ -710,6 +721,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) { "ping", &RPCParser::parseAsIs, 0, 0 }, // { "profile", &RPCParser::parseProfile, 1, 9 }, { "proof_create", &RPCParser::parseProofCreate, 0, 1 }, + { "proof_verify", &RPCParser::parseProofVerify, 2, 2 }, { "random", &RPCParser::parseAsIs, 0, 0 }, { "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 }, { "sign", &RPCParser::parseSignSubmit, 2, 2 }, diff --git a/src/cpp/ripple/CallRPC.h b/src/cpp/ripple/CallRPC.h index 6fa8f27252..a07ea40436 100644 --- a/src/cpp/ripple/CallRPC.h +++ b/src/cpp/ripple/CallRPC.h @@ -35,6 +35,7 @@ protected: Json::Value parseLogLevel(const Json::Value& jvParams); Json::Value parseOwnerInfo(const Json::Value& jvParams); Json::Value parseProofCreate(const Json::Value& jvParams); + Json::Value parseProofVerify(const Json::Value& jvParams); Json::Value parseRandom(const Json::Value& jvParams); Json::Value parseRipplePathFind(const Json::Value& jvParams); Json::Value parseSMS(const Json::Value& jvParams); diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp index 2036a66f67..16d0f3cf19 100644 --- a/src/cpp/ripple/ProofOfWork.cpp +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -13,6 +13,37 @@ SETUP_LOG(); + +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); diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h index 1133a4c29f..f7e0f78ae8 100644 --- a/src/cpp/ripple/ProofOfWork.h +++ b/src/cpp/ripple/ProofOfWork.h @@ -20,6 +20,7 @@ enum POWResult powTOOEASY = 5, // the difficulty increased too much while you solved it }; +bool powResultInfo(POWResult powCode, std::string& strToken, std::string& strHuman); class ProofOfWork { diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index cab60568c8..3d89ad89ca 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -910,6 +910,41 @@ Json::Value RPCHandler::doProofCreate(Json::Value jvRequest, int& cost, ScopedLo return jvResult; } + +// { +// token: +// solution: +// } +Json::Value RPCHandler::doProofVerify(Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder) +{ + // XXX Add ability to check proof against arbitrary secret & time + + Json::Value jvResult; + + if (!jvRequest.isMember("token")) + return rpcError(rpcINVALID_PARAMS); + + if (!jvRequest.isMember("solution")) + return rpcError(rpcINVALID_PARAMS); + + std::string strToken = jvRequest["token"].asString(); + uint256 uSolution(jvRequest["solution"].asString()); + + // XXX Proof should not be marked as used from this + POWResult prResult = theApp->getPowGen().checkProof(strToken, uSolution); + + std::string sToken; + std::string sHuman; + + powResultInfo(prResult, sToken, sHuman); + + jvResult["proof_result"] = sToken; + jvResult["proof_result_code"] = prResult; + jvResult["proof_result_message"] = sHuman; + + return jvResult; +} + // { // account: || // account_index: // optional, defaults to 0. @@ -3377,6 +3412,7 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole, int & { "ping", &RPCHandler::doPing, false, optNone }, // { "profile", &RPCHandler::doProfile, false, optCurrent }, { "proof_create", &RPCHandler::doProofCreate, false, optNone }, + { "proof_verify", &RPCHandler::doProofVerify, true, optNone }, { "random", &RPCHandler::doRandom, false, optNone }, { "ripple_path_find", &RPCHandler::doRipplePathFind, false, optCurrent }, { "sign", &RPCHandler::doSign, false, optCurrent }, diff --git a/src/cpp/ripple/RPCHandler.h b/src/cpp/ripple/RPCHandler.h index d90610f919..41ceed6243 100644 --- a/src/cpp/ripple/RPCHandler.h +++ b/src/cpp/ripple/RPCHandler.h @@ -73,6 +73,7 @@ class RPCHandler Json::Value doPing(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doProfile(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doProofCreate(Json::Value params, int& cost, ScopedLock& mlh); + Json::Value doProofVerify(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doRandom(Json::Value jvRequest, int& cost, ScopedLock& mlh); Json::Value doRipplePathFind(Json::Value jvRequest, int& cost, ScopedLock& mlh); Json::Value doServerInfo(Json::Value params, int& cost, ScopedLock& mlh); // for humans From da406a3506c28e8fa85e5f8e1b9f383ac5f0982a Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Sun, 12 May 2013 12:58:25 +0200 Subject: [PATCH 3/9] RPC: Add proof_solve. --- src/cpp/ripple/CallRPC.cpp | 11 +++++++++++ src/cpp/ripple/CallRPC.h | 1 + src/cpp/ripple/ProofOfWork.cpp | 22 ++++++++++++++++++++++ src/cpp/ripple/ProofOfWork.h | 4 ++++ src/cpp/ripple/RPCHandler.cpp | 24 ++++++++++++++++++++++++ src/cpp/ripple/RPCHandler.h | 1 + 6 files changed, 63 insertions(+) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index 86e5f15378..4160dfea82 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -482,6 +482,16 @@ Json::Value RPCParser::parseProofCreate(const Json::Value& jvParams) return jvRequest; } +// proof_solve +Json::Value RPCParser::parseProofSolve(const Json::Value& jvParams) +{ + Json::Value jvRequest; + + jvRequest["token"] = jvParams[0u].asString(); + + return jvRequest; +} + // proof_verify Json::Value RPCParser::parseProofVerify(const Json::Value& jvParams) { @@ -721,6 +731,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) { "ping", &RPCParser::parseAsIs, 0, 0 }, // { "profile", &RPCParser::parseProfile, 1, 9 }, { "proof_create", &RPCParser::parseProofCreate, 0, 1 }, + { "proof_solve", &RPCParser::parseProofSolve, 1, 1 }, { "proof_verify", &RPCParser::parseProofVerify, 2, 2 }, { "random", &RPCParser::parseAsIs, 0, 0 }, { "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 }, diff --git a/src/cpp/ripple/CallRPC.h b/src/cpp/ripple/CallRPC.h index a07ea40436..01920c19ea 100644 --- a/src/cpp/ripple/CallRPC.h +++ b/src/cpp/ripple/CallRPC.h @@ -35,6 +35,7 @@ protected: Json::Value parseLogLevel(const Json::Value& jvParams); Json::Value parseOwnerInfo(const Json::Value& jvParams); Json::Value parseProofCreate(const Json::Value& jvParams); + Json::Value parseProofSolve(const Json::Value& jvParams); Json::Value parseProofVerify(const Json::Value& jvParams); Json::Value parseRandom(const Json::Value& jvParams); Json::Value parseRipplePathFind(const Json::Value& jvParams); diff --git a/src/cpp/ripple/ProofOfWork.cpp b/src/cpp/ripple/ProofOfWork.cpp index 16d0f3cf19..b38a23ab91 100644 --- a/src/cpp/ripple/ProofOfWork.cpp +++ b/src/cpp/ripple/ProofOfWork.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -48,6 +49,19 @@ const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF const int ProofOfWork::sMaxIterations(1 << 23); const int ProofOfWork::sMaxDifficulty(30); +ProofOfWork::ProofOfWork(const std::string& token) +{ + std::vector 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(fields[2]); +} + bool ProofOfWork::isValid() const { if ((mIterations <= sMaxIterations) && (mTarget >= sMinTarget)) @@ -141,6 +155,14 @@ bool ProofOfWork::checkSolution(const uint256& solution) const 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) { setDifficulty(1); diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h index f7e0f78ae8..1e29ada1d8 100644 --- a/src/cpp/ripple/ProofOfWork.h +++ b/src/cpp/ripple/ProofOfWork.h @@ -43,6 +43,8 @@ public: mToken(token), mChallenge(challenge), mTarget(target), mIterations(iterations) { ; } + ProofOfWork(const std::string& token); + bool isValid() const; uint256 solve(int maxIterations = 2 * sMaxIterations) const; @@ -54,6 +56,8 @@ public: // 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); }; class ProofOfWorkGenerator diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 3d89ad89ca..e39c85c3fd 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -910,6 +910,29 @@ Json::Value RPCHandler::doProofCreate(Json::Value jvRequest, int& cost, ScopedLo return jvResult; } +// { +// token: +// } +Json::Value RPCHandler::doProofSolve(Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder) +{ + Json::Value jvResult; + + if (!jvRequest.isMember("token")) + return rpcError(rpcINVALID_PARAMS); + + std::string strToken = jvRequest["token"].asString(); + + if (!ProofOfWork::validateToken(strToken)) + return rpcError(rpcINVALID_PARAMS); + + ProofOfWork powProof(strToken); + uint256 uSolution = powProof.solve(); + + jvResult["solution"] = uSolution.GetHex(); + + return jvResult; +} + // { // token: @@ -3412,6 +3435,7 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole, int & { "ping", &RPCHandler::doPing, false, optNone }, // { "profile", &RPCHandler::doProfile, false, optCurrent }, { "proof_create", &RPCHandler::doProofCreate, false, optNone }, + { "proof_solve", &RPCHandler::doProofSolve, true, optNone }, { "proof_verify", &RPCHandler::doProofVerify, true, optNone }, { "random", &RPCHandler::doRandom, false, optNone }, { "ripple_path_find", &RPCHandler::doRipplePathFind, false, optCurrent }, diff --git a/src/cpp/ripple/RPCHandler.h b/src/cpp/ripple/RPCHandler.h index 41ceed6243..ba9c171513 100644 --- a/src/cpp/ripple/RPCHandler.h +++ b/src/cpp/ripple/RPCHandler.h @@ -73,6 +73,7 @@ class RPCHandler Json::Value doPing(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doProfile(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doProofCreate(Json::Value params, int& cost, ScopedLock& mlh); + Json::Value doProofSolve(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doProofVerify(Json::Value params, int& cost, ScopedLock& mlh); Json::Value doRandom(Json::Value jvRequest, int& cost, ScopedLock& mlh); Json::Value doRipplePathFind(Json::Value jvRequest, int& cost, ScopedLock& mlh); From 5e649921bf235cdeff7319582ad67c67acf44b2c Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Sun, 12 May 2013 13:51:16 +0200 Subject: [PATCH 4/9] RPC: Add ability to specify a custom secret in proof_create. --- src/cpp/ripple/CallRPC.cpp | 9 ++++++--- src/cpp/ripple/ProofOfWork.h | 1 + src/cpp/ripple/RPCHandler.cpp | 37 +++++++++++++++++++++++------------ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index 4160dfea82..1eb4d919fa 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -471,14 +471,17 @@ Json::Value RPCParser::parseAccountRaw(const Json::Value& jvParams, bool bPeer) return jvRequest; } -// proof_create [] +// proof_create [] [] Json::Value RPCParser::parseProofCreate(const Json::Value& jvParams) { Json::Value jvRequest; - if (1 == jvParams.size()) + if (jvParams.size() >= 1) jvRequest["difficulty"] = jvParams[0u].asInt(); + if (jvParams.size() >= 2) + jvRequest["secret"] = jvParams[1u].asString(); + return jvRequest; } @@ -730,7 +733,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) { "peers", &RPCParser::parseAsIs, 0, 0 }, { "ping", &RPCParser::parseAsIs, 0, 0 }, // { "profile", &RPCParser::parseProfile, 1, 9 }, - { "proof_create", &RPCParser::parseProofCreate, 0, 1 }, + { "proof_create", &RPCParser::parseProofCreate, 0, 2 }, { "proof_solve", &RPCParser::parseProofSolve, 1, 1 }, { "proof_verify", &RPCParser::parseProofVerify, 2, 2 }, { "random", &RPCParser::parseAsIs, 0, 0 }, diff --git a/src/cpp/ripple/ProofOfWork.h b/src/cpp/ripple/ProofOfWork.h index 1e29ada1d8..0d476bbd78 100644 --- a/src/cpp/ripple/ProofOfWork.h +++ b/src/cpp/ripple/ProofOfWork.h @@ -90,6 +90,7 @@ public: void sweep(void); const uint256& getSecret() const { return mSecret; } + void setSecret(const uint256& secret) { mSecret = secret; } static int getPowEntry(const uint256& target, int iterations); }; diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index e39c85c3fd..078e219652 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -879,27 +879,38 @@ Json::Value RPCHandler::doProfile(Json::Value jvRequest, int& cost, ScopedLock& } // { -// difficulty: // optional, if set, a temporary generator is -// // instantiated and its secret included +// // if either of these parameters is set, a custom generator is used +// difficulty: // optional +// secret: // optional // } Json::Value RPCHandler::doProofCreate(Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder) { - // XXX: Add ability to create proof with arbitrary secret and time + // XXX: Add ability to create proof with arbitrary time Json::Value jvResult(Json::objectValue); - if (jvRequest.isMember("difficulty")) + if (jvRequest.isMember("difficulty") || jvRequest.isMember("secret")) { - if (!jvRequest["difficulty"].isIntegral()) - return rpcError(rpcINVALID_PARAMS); - - int iDifficulty = jvRequest["difficulty"].asInt(); - - if (iDifficulty < 0 || iDifficulty > ProofOfWork::sMaxDifficulty) - return rpcError(rpcINVALID_PARAMS); - ProofOfWorkGenerator pgGen; - pgGen.setDifficulty(iDifficulty); + + if (jvRequest.isMember("difficulty")) + { + if (!jvRequest["difficulty"].isIntegral()) + return rpcError(rpcINVALID_PARAMS); + + int iDifficulty = jvRequest["difficulty"].asInt(); + + if (iDifficulty < 0 || iDifficulty > ProofOfWork::sMaxDifficulty) + return rpcError(rpcINVALID_PARAMS); + + pgGen.setDifficulty(iDifficulty); + } + + if (jvRequest.isMember("secret")) + { + uint256 uSecret(jvRequest["secret"].asString()); + pgGen.setSecret(uSecret); + } jvResult["token"] = pgGen.getProof().getToken(); jvResult["secret"] = pgGen.getSecret().GetHex(); From 508db42aba98781e50f03038ec842deee5efa911 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 13 May 2013 10:16:19 +0200 Subject: [PATCH 5/9] RPC: Add ability to specify a custom secret in proof_verify. --- src/cpp/ripple/CallRPC.cpp | 10 +++++++-- src/cpp/ripple/RPCHandler.cpp | 40 ++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp index 1eb4d919fa..78fc2579ca 100644 --- a/src/cpp/ripple/CallRPC.cpp +++ b/src/cpp/ripple/CallRPC.cpp @@ -495,7 +495,7 @@ Json::Value RPCParser::parseProofSolve(const Json::Value& jvParams) return jvRequest; } -// proof_verify +// proof_verify [] [] Json::Value RPCParser::parseProofVerify(const Json::Value& jvParams) { Json::Value jvRequest; @@ -503,6 +503,12 @@ Json::Value RPCParser::parseProofVerify(const Json::Value& jvParams) jvRequest["token"] = jvParams[0u].asString(); jvRequest["solution"] = jvParams[1u].asString(); + if (jvParams.size() >= 3) + jvRequest["difficulty"] = jvParams[2u].asInt(); + + if (jvParams.size() >= 4) + jvRequest["secret"] = jvParams[3u].asString(); + return jvRequest; } @@ -735,7 +741,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams) // { "profile", &RPCParser::parseProfile, 1, 9 }, { "proof_create", &RPCParser::parseProofCreate, 0, 2 }, { "proof_solve", &RPCParser::parseProofSolve, 1, 1 }, - { "proof_verify", &RPCParser::parseProofVerify, 2, 2 }, + { "proof_verify", &RPCParser::parseProofVerify, 2, 4 }, { "random", &RPCParser::parseAsIs, 0, 0 }, { "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 }, { "sign", &RPCParser::parseSignSubmit, 2, 2 }, diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 078e219652..02af628873 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -948,10 +948,13 @@ Json::Value RPCHandler::doProofSolve(Json::Value jvRequest, int& cost, ScopedLoc // { // token: // solution: +// // if either of these parameters is set, a custom verifier is used +// difficulty: // optional +// secret: // optional // } Json::Value RPCHandler::doProofVerify(Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder) { - // XXX Add ability to check proof against arbitrary secret & time + // XXX Add ability to check proof against arbitrary time Json::Value jvResult; @@ -964,8 +967,39 @@ Json::Value RPCHandler::doProofVerify(Json::Value jvRequest, int& cost, ScopedLo std::string strToken = jvRequest["token"].asString(); uint256 uSolution(jvRequest["solution"].asString()); - // XXX Proof should not be marked as used from this - POWResult prResult = theApp->getPowGen().checkProof(strToken, uSolution); + POWResult prResult; + if (jvRequest.isMember("difficulty") || jvRequest.isMember("secret")) + { + ProofOfWorkGenerator pgGen; + + if (jvRequest.isMember("difficulty")) + { + if (!jvRequest["difficulty"].isIntegral()) + return rpcError(rpcINVALID_PARAMS); + + int iDifficulty = jvRequest["difficulty"].asInt(); + + if (iDifficulty < 0 || iDifficulty > ProofOfWork::sMaxDifficulty) + return rpcError(rpcINVALID_PARAMS); + + pgGen.setDifficulty(iDifficulty); + } + + if (jvRequest.isMember("secret")) + { + uint256 uSecret(jvRequest["secret"].asString()); + pgGen.setSecret(uSecret); + } + + prResult = pgGen.checkProof(strToken, uSolution); + + jvResult["secret"] = pgGen.getSecret().GetHex(); + } + else + { + // XXX Proof should not be marked as used from this + prResult = theApp->getPowGen().checkProof(strToken, uSolution); + } std::string sToken; std::string sHuman; From a1a661a024b7e02f5303e4cb0361cacd912ab95f Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 13 May 2013 10:17:32 +0200 Subject: [PATCH 6/9] CLI: Add proof_* to command line help. --- src/cpp/ripple/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/ripple/main.cpp b/src/cpp/ripple/main.cpp index 49e8371a79..15a23767d2 100644 --- a/src/cpp/ripple/main.cpp +++ b/src/cpp/ripple/main.cpp @@ -91,6 +91,9 @@ void printHelp(const po::options_description& desc) cerr << " ledger_header " << endl; cerr << " logrotate " << endl; cerr << " peers" << endl; + cerr << " proof_create [] []" << endl; + cerr << " proof_solve " << endl; + cerr << " proof_verify [] []" << endl; cerr << " random" << endl; cerr << " ripple ..." << endl; cerr << " ripple_path_find []" << endl; From e627daa4104868a9acf4b88d5cce05d5b78a0e44 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 13 May 2013 11:32:23 +0200 Subject: [PATCH 7/9] JS: Use correct inheritance for Server class. Fixes test suite in Node 0.10.x. --- test/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/server.js b/test/server.js index 80853fd1d7..f47189cafd 100644 --- a/test/server.js +++ b/test/server.js @@ -56,7 +56,7 @@ var Server = function (name, config, verbose) { } }; -Server.prototype = new EventEmitter; +util.inherits(Server, EventEmitter); Server.from_config = function (name, verbose) { return new Server(name, config.servers[name], verbose); From 10993f19998136ec0936cdaeb58871086baecdb2 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 13 May 2013 11:33:23 +0200 Subject: [PATCH 8/9] JS: Update to latest buster. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61445bbd75..8fc913ca76 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "simple-jsonrpc": "~0.0.1" }, "devDependencies": { - "buster": "~0.6.2" + "buster": "~0.7.0" }, "scripts": { From 07ed7812f326ff159d52d31e94998a63388da759 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 13 May 2013 11:39:10 +0200 Subject: [PATCH 9/9] JS: Revert that last, buster 0.7 isn't out yet. Back to 0.6.x. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8fc913ca76..17d814811d 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "simple-jsonrpc": "~0.0.1" }, "devDependencies": { - "buster": "~0.7.0" + "buster": "~0.6.12" }, "scripts": {