Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2013-03-08 10:30:30 -08:00
15 changed files with 235 additions and 174 deletions

View File

@@ -109,6 +109,7 @@
<ClCompile Include="src\cpp\ripple\DBInit.cpp" /> <ClCompile Include="src\cpp\ripple\DBInit.cpp" />
<ClCompile Include="src\cpp\ripple\DeterministicKeys.cpp" /> <ClCompile Include="src\cpp\ripple\DeterministicKeys.cpp" />
<ClCompile Include="src\cpp\ripple\ECIES.cpp" /> <ClCompile Include="src\cpp\ripple\ECIES.cpp" />
<ClCompile Include="src\cpp\ripple\FeatureTable.cpp" />
<ClCompile Include="src\cpp\ripple\FieldNames.cpp" /> <ClCompile Include="src\cpp\ripple\FieldNames.cpp" />
<ClCompile Include="src\cpp\ripple\HashedObject.cpp" /> <ClCompile Include="src\cpp\ripple\HashedObject.cpp" />
<ClCompile Include="src\cpp\ripple\HTTPRequest.cpp" /> <ClCompile Include="src\cpp\ripple\HTTPRequest.cpp" />
@@ -295,8 +296,9 @@
<None Include="html\newcoin.html"> <None Include="html\newcoin.html">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<None Include="newcoind.cfg" />
<None Include="README" /> <None Include="README" />
<None Include="ripple-example.txt" />
<None Include="rippled-example.cfg" />
<None Include="SConstruct" /> <None Include="SConstruct" />
<CustomBuild Include="src\cpp\ripple\ripple.proto"> <CustomBuild Include="src\cpp\ripple\ripple.proto">
<FileType>Document</FileType> <FileType>Document</FileType>
@@ -307,7 +309,7 @@
<None Include="test\server.js" /> <None Include="test\server.js" />
<None Include="test\standalone-test.js" /> <None Include="test\standalone-test.js" />
<None Include="test\utils.js" /> <None Include="test\utils.js" />
<None Include="validators.txt" /> <None Include="validators-example.txt" />
<None Include="wallet.xml" /> <None Include="wallet.xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -234,6 +234,7 @@ void SqliteDatabase::runWal()
std::set<std::string> walSet; std::set<std::string> walSet;
std::string name = sqlite3_db_filename(mConnection, "main"); std::string name = sqlite3_db_filename(mConnection, "main");
int pass = 1;
while (1) while (1)
{ {
{ {
@@ -255,8 +256,11 @@ void SqliteDatabase::runWal()
cLog((ret == SQLITE_LOCKED) ? lsTRACE : lsWARNING) << "WAL " << mHost << ":" cLog((ret == SQLITE_LOCKED) ? lsTRACE : lsWARNING) << "WAL " << mHost << ":"
<< db << " error " << ret; << db << " error " << ret;
} }
else
cLog(lsTRACE) << "WAL(" << mHost << "): pass=" << pass << ", frames=" << log << ", written=" << ckpt;
} }
walSet.clear(); walSet.clear();
++pass;
} }
} }

View File

@@ -26,9 +26,9 @@ Application* theApp = NULL;
DatabaseCon::DatabaseCon(const std::string& strName, const char *initStrings[], int initCount) DatabaseCon::DatabaseCon(const std::string& strName, const char *initStrings[], int initCount)
{ {
boost::filesystem::path pPath = theConfig.RUN_STANDALONE && !Config::LOAD boost::filesystem::path pPath = (theConfig.RUN_STANDALONE && (!theConfig.START_UP != Config::LOAD))
? "" // Use temporary files. ? "" // Use temporary files.
: theConfig.DATA_DIR / strName; // Use regular db files. : (theConfig.DATA_DIR / strName); // Use regular db files.
mDatabase = new SqliteDatabase(pPath.string().c_str()); mDatabase = new SqliteDatabase(pPath.string().c_str());
mDatabase->connect(); mDatabase->connect();
@@ -45,7 +45,7 @@ DatabaseCon::~DatabaseCon()
Application::Application() : Application::Application() :
mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster), mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster),
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300), mSLECache("LedgerEntryCache", 4096, 120), mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300), mSLECache("LedgerEntryCache", 4096, 120),
mSNTPClient(mAuxService), mRPCHandler(&mNetOps), mFeeTrack(), mSNTPClient(mAuxService), mFeeTrack(),
mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL), mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL), mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
mSweepTimer(mAuxService), mShutdown(false) mSweepTimer(mAuxService), mShutdown(false)

View File

@@ -64,7 +64,6 @@ class Application
SLECache mSLECache; SLECache mSLECache;
SNTPClient mSNTPClient; SNTPClient mSNTPClient;
JobQueue mJobQueue; JobQueue mJobQueue;
RPCHandler mRPCHandler;
ProofOfWorkGenerator mPOWGen; ProofOfWorkGenerator mPOWGen;
LoadManager mLoadMgr; LoadManager mLoadMgr;
LoadFeeTrack mFeeTrack; LoadFeeTrack mFeeTrack;
@@ -114,7 +113,6 @@ public:
ValidationCollection& getValidations() { return mValidations; } ValidationCollection& getValidations() { return mValidations; }
JobQueue& getJobQueue() { return mJobQueue; } JobQueue& getJobQueue() { return mJobQueue; }
SuppressionTable& getSuppression() { return mSuppressions; } SuppressionTable& getSuppression() { return mSuppressions; }
RPCHandler& getRPCHandler() { return mRPCHandler; }
boost::recursive_mutex& getMasterLock() { return mMasterLock; } boost::recursive_mutex& getMasterLock() { return mMasterLock; }
ProofOfWorkGenerator& getPowGen() { return mPOWGen; } ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
LoadManager& getLoadManager() { return mLoadMgr; } LoadManager& getLoadManager() { return mLoadMgr; }

View File

@@ -131,6 +131,7 @@ void LoadManager::canonicalize(LoadSource& source, int now) const
} }
bool LoadManager::shouldWarn(LoadSource& source) const bool LoadManager::shouldWarn(LoadSource& source) const
{
{ {
boost::mutex::scoped_lock sl(mLock); boost::mutex::scoped_lock sl(mLock);
@@ -140,16 +141,22 @@ bool LoadManager::shouldWarn(LoadSource& source) const
return false; return false;
source.mLastWarning = now; source.mLastWarning = now;
}
logWarning(source.getName());
return true; return true;
} }
bool LoadManager::shouldCutoff(LoadSource& source) const bool LoadManager::shouldCutoff(LoadSource& source) const
{
{ {
boost::mutex::scoped_lock sl(mLock); boost::mutex::scoped_lock sl(mLock);
int now = upTime(); int now = upTime();
canonicalize(source, now); canonicalize(source, now);
return !source.isPrivileged() && (source.mBalance < mDebitLimit); if (!source.isPrivileged() || (source.mBalance > mDebitLimit))
return false;
}
logDisconnect(source.getName());
return true;
} }
bool LoadManager::adjust(LoadSource& source, LoadType t) const bool LoadManager::adjust(LoadSource& source, LoadType t) const
@@ -160,7 +167,6 @@ bool LoadManager::adjust(LoadSource& source, LoadType t) const
bool LoadManager::adjust(LoadSource& source, int credits) const bool LoadManager::adjust(LoadSource& source, int credits) const
{ // return: true = need to warn/cutoff { // return: true = need to warn/cutoff
boost::mutex::scoped_lock sl(mLock);
// We do it this way in case we want to add exponential decay later // We do it this way in case we want to add exponential decay later
int now = upTime(); int now = upTime();
@@ -172,13 +178,10 @@ bool LoadManager::adjust(LoadSource& source, int credits) const
if (source.isPrivileged()) // privileged sources never warn/cutoff if (source.isPrivileged()) // privileged sources never warn/cutoff
return false; return false;
if (source.mBalance < mDebitLimit) // over-limit if ((source.mBalance >= mDebitLimit) && (source.mLastWarning == now)) // no need to warn
return true;
if ((source.mBalance < mDebitWarn) && (source.mLastWarning != now)) // need to warn
return true;
return false; return false;
return true;
} }
uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint64 div) uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint64 div)
@@ -345,6 +348,22 @@ void LoadManager::threadEntry()
} }
} }
void LoadManager::logWarning(const std::string& source) const
{
if (source.empty())
cLog(lsDEBUG) << "Load warning from empty source";
else
cLog(lsINFO) << "Load warning: " << source;
}
void LoadManager::logDisconnect(const std::string& source) const
{
if (source.empty())
cLog(lsINFO) << "Disconnect for empty source";
else
cLog(lsWARNING) << "Disconnect for: " << source;
}
BOOST_AUTO_TEST_SUITE(LoadManager_test) BOOST_AUTO_TEST_SUITE(LoadManager_test)
BOOST_AUTO_TEST_CASE(LoadFeeTrack_test) BOOST_AUTO_TEST_CASE(LoadFeeTrack_test)

View File

@@ -61,14 +61,20 @@ public:
static const int lsfOutbound = 2; // outbound connection static const int lsfOutbound = 2; // outbound connection
protected: protected:
std::string mName;
int mBalance; int mBalance;
int mFlags; int mFlags;
int mLastUpdate; int mLastUpdate;
int mLastWarning; int mLastWarning;
public: public:
LoadSource() : mBalance(0), mFlags(0), mLastWarning(0) LoadSource(bool admin) : mBalance(0), mFlags(admin ? lsfPrivileged : 0), mLastUpdate(upTime()), mLastWarning(0)
{ mLastUpdate = upTime(); } { ; }
LoadSource(const std::string& name) : mName(name), mBalance(0), mFlags(0), mLastUpdate(upTime()), mLastWarning(0)
{ ; }
void rename(const std::string& name) { mName = name; }
const std::string& getName() { return mName; }
bool isPrivileged() const { return (mFlags & lsfPrivileged) != 0; } bool isPrivileged() const { return (mFlags & lsfPrivileged) != 0; }
void setPrivileged() { mFlags |= lsfPrivileged; } void setPrivileged() { mFlags |= lsfPrivileged; }
@@ -106,7 +112,7 @@ protected:
public: public:
LoadManager(int creditRate = 10, int creditLimit = 50, int debitWarn = -50, int debitLimit = -100); LoadManager(int creditRate = 100, int creditLimit = 500, int debitWarn = -500, int debitLimit = -1000);
~LoadManager(); ~LoadManager();
void init(); void init();
@@ -124,6 +130,9 @@ public:
bool adjust(LoadSource&, int credits) const; // return value: false=balance okay, true=warn/cutoff bool adjust(LoadSource&, int credits) const; // return value: false=balance okay, true=warn/cutoff
bool adjust(LoadSource&, LoadType l) const; bool adjust(LoadSource&, LoadType l) const;
void logWarning(const std::string&) const;
void logDisconnect(const std::string&) const;
int getCost(LoadType t) { return mCosts[static_cast<int>(t)].mCost; } int getCost(LoadType t) { return mCosts[static_cast<int>(t)].mCost; }
int getUptime(); int getUptime();
}; };

View File

@@ -34,6 +34,8 @@ Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx,
mActive(2), mActive(2),
mCluster(false), mCluster(false),
mPeerId(peerID), mPeerId(peerID),
mPrivate(false),
mLoad(""),
mSocketSsl(io_service, ctx), mSocketSsl(io_service, ctx),
mActivityTimer(io_service) mActivityTimer(io_service)
{ {
@@ -77,6 +79,7 @@ void Peer::handleWrite(const boost::system::error_code& error, size_t bytes_tran
void Peer::setIpPort(const std::string& strIP, int iPort) void Peer::setIpPort(const std::string& strIP, int iPort)
{ {
mIpPort = make_pair(strIP, iPort); mIpPort = make_pair(strIP, iPort);
mLoad.rename(strIP);
cLog(lsDEBUG) << "Peer: Set: " cLog(lsDEBUG) << "Peer: Set: "
<< ADDRESS(this) << "> " << ADDRESS(this) << "> "

View File

@@ -25,6 +25,10 @@
SETUP_LOG(); SETUP_LOG();
static const int rpcCOST_DEFAULT = 10;
static const int rpcCOST_EXCEPTION = 20;
static const int rpcCOST_EXPENSIVE = 50;
int iAdminGet(const Json::Value& jvRequest, const std::string& strRemoteIp) int iAdminGet(const Json::Value& jvRequest, const std::string& strRemoteIp)
{ {
int iRole; int iRole;
@@ -63,15 +67,11 @@ int iAdminGet(const Json::Value& jvRequest, const std::string& strRemoteIp)
return iRole; return iRole;
} }
RPCHandler::RPCHandler(NetworkOPs* netOps) RPCHandler::RPCHandler(NetworkOPs* netOps) : mNetOps(netOps)
{ { ; }
mNetOps = netOps;
}
RPCHandler::RPCHandler(NetworkOPs* netOps, InfoSub::pointer infoSub) : mInfoSub(infoSub) RPCHandler::RPCHandler(NetworkOPs* netOps, InfoSub::pointer infoSub) : mNetOps(netOps), mInfoSub(infoSub)
{ { ; }
mNetOps = netOps;
}
Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit) Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit)
{ {
@@ -565,7 +565,7 @@ Json::Value RPCHandler::accountFromString(Ledger::ref lrLedger, RippleAddress& n
// ledger_hash : <ledger> // ledger_hash : <ledger>
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
Json::Value RPCHandler::doAccountInfo(Json::Value jvRequest) Json::Value RPCHandler::doAccountInfo(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -610,7 +610,7 @@ Json::Value RPCHandler::doAccountInfo(Json::Value jvRequest)
// port: <number> // port: <number>
// } // }
// XXX Might allow domain for manual connections. // XXX Might allow domain for manual connections.
Json::Value RPCHandler::doConnect(Json::Value jvRequest) Json::Value RPCHandler::doConnect(Json::Value jvRequest, int& cost)
{ {
if (theConfig.RUN_STANDALONE) if (theConfig.RUN_STANDALONE)
return "cannot connect in standalone mode"; return "cannot connect in standalone mode";
@@ -631,7 +631,7 @@ Json::Value RPCHandler::doConnect(Json::Value jvRequest)
// { // {
// key: <string> // key: <string>
// } // }
Json::Value RPCHandler::doDataDelete(Json::Value jvRequest) Json::Value RPCHandler::doDataDelete(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("key")) if (!jvRequest.isMember("key"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -657,7 +657,7 @@ Json::Value RPCHandler::doDataDelete(Json::Value jvRequest)
// { // {
// key: <string> // key: <string>
// } // }
Json::Value RPCHandler::doDataFetch(Json::Value jvRequest) Json::Value RPCHandler::doDataFetch(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("key")) if (!jvRequest.isMember("key"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -680,7 +680,7 @@ Json::Value RPCHandler::doDataFetch(Json::Value jvRequest)
// key: <string> // key: <string>
// value: <string> // value: <string>
// } // }
Json::Value RPCHandler::doDataStore(Json::Value jvRequest) Json::Value RPCHandler::doDataStore(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("key") if (!jvRequest.isMember("key")
|| !jvRequest.isMember("value")) || !jvRequest.isMember("value"))
@@ -740,7 +740,7 @@ Json::Value RPCHandler::doNicknameInfo(Json::Value params)
// 'account_index' : <index> // optional // 'account_index' : <index> // optional
// } // }
// XXX This would be better if it took the ledger. // XXX This would be better if it took the ledger.
Json::Value RPCHandler::doOwnerInfo(Json::Value jvRequest) Json::Value RPCHandler::doOwnerInfo(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("account") && !jvRequest.isMember("ident")) if (!jvRequest.isMember("account") && !jvRequest.isMember("ident"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -765,7 +765,7 @@ Json::Value RPCHandler::doOwnerInfo(Json::Value jvRequest)
return ret; return ret;
} }
Json::Value RPCHandler::doPeers(Json::Value) Json::Value RPCHandler::doPeers(Json::Value, int& cost)
{ {
Json::Value jvResult(Json::objectValue); Json::Value jvResult(Json::objectValue);
@@ -774,7 +774,7 @@ Json::Value RPCHandler::doPeers(Json::Value)
return jvResult; return jvResult;
} }
Json::Value RPCHandler::doPing(Json::Value) Json::Value RPCHandler::doPing(Json::Value, int& cost)
{ {
return Json::Value(Json::objectValue); return Json::Value(Json::objectValue);
} }
@@ -784,7 +784,7 @@ Json::Value RPCHandler::doPing(Json::Value)
// issuer is the offering account // issuer is the offering account
// --> submit: 'submit|true|false': defaults to false // --> submit: 'submit|true|false': defaults to false
// Prior to running allow each to have a credit line of what they will be getting from the other account. // Prior to running allow each to have a credit line of what they will be getting from the other account.
Json::Value RPCHandler::doProfile(Json::Value jvRequest) Json::Value RPCHandler::doProfile(Json::Value jvRequest, int& cost)
{ {
/* need to fix now that sharedOfferCreate is gone /* need to fix now that sharedOfferCreate is gone
int iArgs = jvRequest.size(); int iArgs = jvRequest.size();
@@ -877,7 +877,7 @@ Json::Value RPCHandler::doProfile(Json::Value jvRequest)
// ledger_hash : <ledger> // ledger_hash : <ledger>
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
Json::Value RPCHandler::doAccountLines(Json::Value jvRequest) Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -956,7 +956,7 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest)
// ledger_hash : <ledger> // ledger_hash : <ledger>
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest) Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -1027,7 +1027,7 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest)
// "limit" : integer, // Optional. // "limit" : integer, // Optional.
// "proof" : boolean // Defaults to false. // "proof" : boolean // Defaults to false.
// } // }
Json::Value RPCHandler::doBookOffers(Json::Value jvRequest) Json::Value RPCHandler::doBookOffers(Json::Value jvRequest, int& cost)
{ {
if (theApp->getJobQueue().getJobCountGE(jtCLIENT) > 200) if (theApp->getJobQueue().getJobCountGE(jtCLIENT) > 200)
{ {
@@ -1124,7 +1124,7 @@ Json::Value RPCHandler::doBookOffers(Json::Value jvRequest)
// { // {
// random: <uint256> // random: <uint256>
// } // }
Json::Value RPCHandler::doRandom(Json::Value jvRequest) Json::Value RPCHandler::doRandom(Json::Value jvRequest, int& cost)
{ {
uint256 uRandom; uint256 uRandom;
@@ -1150,7 +1150,7 @@ Json::Value RPCHandler::doRandom(Json::Value jvRequest)
// - Allows clients to verify path exists. // - Allows clients to verify path exists.
// - Return canonicalized path. // - Return canonicalized path.
// - From a trusted server, allows clients to use path without manipulation. // - From a trusted server, allows clients to use path without manipulation.
Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest) Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest, int& cost)
{ {
RippleAddress raSrc; RippleAddress raSrc;
RippleAddress raDst; RippleAddress raDst;
@@ -1230,6 +1230,7 @@ Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest)
} }
} }
cost = rpcCOST_EXPENSIVE;
Ledger::pointer lSnapShot = boost::make_shared<Ledger>(boost::ref(*lpLedger), false); Ledger::pointer lSnapShot = boost::make_shared<Ledger>(boost::ref(*lpLedger), false);
LedgerEntrySet lesSnapshot(lSnapShot); LedgerEntrySet lesSnapshot(lSnapShot);
@@ -1363,8 +1364,9 @@ Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest)
// tx_json: <object>, // tx_json: <object>,
// secret: <secret> // secret: <secret>
// } // }
Json::Value RPCHandler::doSign(Json::Value jvRequest) Json::Value RPCHandler::doSign(Json::Value jvRequest, int& cost)
{ {
cost = rpcCOST_EXPENSIVE;
return transactionSign(jvRequest, false); return transactionSign(jvRequest, false);
} }
@@ -1372,7 +1374,7 @@ Json::Value RPCHandler::doSign(Json::Value jvRequest)
// tx_json: <object>, // tx_json: <object>,
// secret: <secret> // secret: <secret>
// } // }
Json::Value RPCHandler::doSubmit(Json::Value jvRequest) Json::Value RPCHandler::doSubmit(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("tx_blob")) if (!jvRequest.isMember("tx_blob"))
{ {
@@ -1387,6 +1389,7 @@ Json::Value RPCHandler::doSubmit(Json::Value jvRequest)
{ {
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
} }
cost = rpcCOST_EXPENSIVE;
Serializer sTrans(vucBlob); Serializer sTrans(vucBlob);
SerializerIterator sitTrans(sTrans); SerializerIterator sitTrans(sTrans);
@@ -1458,7 +1461,7 @@ Json::Value RPCHandler::doSubmit(Json::Value jvRequest)
} }
} }
Json::Value RPCHandler::doConsensusInfo(Json::Value) Json::Value RPCHandler::doConsensusInfo(Json::Value, int& cost)
{ {
Json::Value ret(Json::objectValue); Json::Value ret(Json::objectValue);
@@ -1467,7 +1470,7 @@ Json::Value RPCHandler::doConsensusInfo(Json::Value)
return ret; return ret;
} }
Json::Value RPCHandler::doServerInfo(Json::Value) Json::Value RPCHandler::doServerInfo(Json::Value, int& cost)
{ {
Json::Value ret(Json::objectValue); Json::Value ret(Json::objectValue);
@@ -1476,7 +1479,7 @@ Json::Value RPCHandler::doServerInfo(Json::Value)
return ret; return ret;
} }
Json::Value RPCHandler::doServerState(Json::Value) Json::Value RPCHandler::doServerState(Json::Value, int& cost)
{ {
Json::Value ret(Json::objectValue); Json::Value ret(Json::objectValue);
@@ -1488,7 +1491,7 @@ Json::Value RPCHandler::doServerState(Json::Value)
// { // {
// start: <index> // start: <index>
// } // }
Json::Value RPCHandler::doTxHistory(Json::Value jvRequest) Json::Value RPCHandler::doTxHistory(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("start")) if (!jvRequest.isMember("start"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -1522,7 +1525,7 @@ Json::Value RPCHandler::doTxHistory(Json::Value jvRequest)
// { // {
// transaction: <hex> // transaction: <hex>
// } // }
Json::Value RPCHandler::doTx(Json::Value jvRequest) Json::Value RPCHandler::doTx(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("transaction")) if (!jvRequest.isMember("transaction"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -1582,7 +1585,7 @@ Json::Value RPCHandler::doTx(Json::Value jvRequest)
return rpcError(rpcNOT_IMPL); return rpcError(rpcNOT_IMPL);
} }
Json::Value RPCHandler::doLedgerClosed(Json::Value) Json::Value RPCHandler::doLedgerClosed(Json::Value, int& cost)
{ {
Json::Value jvResult; Json::Value jvResult;
@@ -1595,7 +1598,7 @@ Json::Value RPCHandler::doLedgerClosed(Json::Value)
return jvResult; return jvResult;
} }
Json::Value RPCHandler::doLedgerCurrent(Json::Value) Json::Value RPCHandler::doLedgerCurrent(Json::Value, int& cost)
{ {
Json::Value jvResult; Json::Value jvResult;
@@ -1609,7 +1612,7 @@ Json::Value RPCHandler::doLedgerCurrent(Json::Value)
// ledger: 'current' | 'closed' | <uint256> | <number>, // optional // ledger: 'current' | 'closed' | <uint256> | <number>, // optional
// full: true | false // optional, defaults to false. // full: true | false // optional, defaults to false.
// } // }
Json::Value RPCHandler::doLedger(Json::Value jvRequest) Json::Value RPCHandler::doLedger(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("ledger")) if (!jvRequest.isMember("ledger"))
{ {
@@ -1655,7 +1658,7 @@ Json::Value RPCHandler::doLedger(Json::Value jvRequest)
// FIXME: Require admin. // FIXME: Require admin.
// FIXME: Doesn't report database holes. // FIXME: Doesn't report database holes.
// FIXME: For consistency change inputs to: ledger_index, ledger_index_min, ledger_index_max. // FIXME: For consistency change inputs to: ledger_index, ledger_index_min, ledger_index_max.
Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest) Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest, int& cost)
{ {
RippleAddress raAccount; RippleAddress raAccount;
uint32 minLedger; uint32 minLedger;
@@ -1752,7 +1755,7 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest)
// } // }
// //
// This command requires admin access because it makes no sense to ask an untrusted server for this. // This command requires admin access because it makes no sense to ask an untrusted server for this.
Json::Value RPCHandler::doValidationCreate(Json::Value jvRequest) { Json::Value RPCHandler::doValidationCreate(Json::Value jvRequest, int& cost) {
RippleAddress raSeed; RippleAddress raSeed;
Json::Value obj(Json::objectValue); Json::Value obj(Json::objectValue);
@@ -1777,7 +1780,7 @@ Json::Value RPCHandler::doValidationCreate(Json::Value jvRequest) {
// { // {
// secret: <string> // secret: <string>
// } // }
Json::Value RPCHandler::doValidationSeed(Json::Value jvRequest) { Json::Value RPCHandler::doValidationSeed(Json::Value jvRequest, int& cost) {
Json::Value obj(Json::objectValue); Json::Value obj(Json::objectValue);
if (!jvRequest.isMember("secret")) if (!jvRequest.isMember("secret"))
@@ -1844,7 +1847,7 @@ Json::Value RPCHandler::accounts(Ledger::ref lrLedger, const RippleAddress& naMa
// ledger_hash : <ledger> // ledger_hash : <ledger>
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
Json::Value RPCHandler::doWalletAccounts(Json::Value jvRequest) Json::Value RPCHandler::doWalletAccounts(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -1887,7 +1890,7 @@ Json::Value RPCHandler::doWalletAccounts(Json::Value jvRequest)
} }
} }
Json::Value RPCHandler::doLogRotate(Json::Value) Json::Value RPCHandler::doLogRotate(Json::Value, int& cost)
{ {
return Log::rotateLog(); return Log::rotateLog();
} }
@@ -1895,7 +1898,7 @@ Json::Value RPCHandler::doLogRotate(Json::Value)
// { // {
// passphrase: <string> // passphrase: <string>
// } // }
Json::Value RPCHandler::doWalletPropose(Json::Value jvRequest) Json::Value RPCHandler::doWalletPropose(Json::Value jvRequest, int& cost)
{ {
RippleAddress naSeed; RippleAddress naSeed;
RippleAddress naAccount; RippleAddress naAccount;
@@ -1925,7 +1928,7 @@ Json::Value RPCHandler::doWalletPropose(Json::Value jvRequest)
// { // {
// secret: <string> // secret: <string>
// } // }
Json::Value RPCHandler::doWalletSeed(Json::Value jvRequest) Json::Value RPCHandler::doWalletSeed(Json::Value jvRequest, int& cost)
{ {
RippleAddress raSeed; RippleAddress raSeed;
bool bSecret = jvRequest.isMember("secret"); bool bSecret = jvRequest.isMember("secret");
@@ -1964,7 +1967,7 @@ Json::Value RPCHandler::doWalletSeed(Json::Value jvRequest)
// username: <string>, // username: <string>,
// password: <string> // password: <string>
// } // }
Json::Value RPCHandler::doLogin(Json::Value jvRequest) Json::Value RPCHandler::doLogin(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("username") if (!jvRequest.isMember("username")
|| !jvRequest.isMember("password")) || !jvRequest.isMember("password"))
@@ -2000,7 +2003,7 @@ static void textTime(std::string& text, int& seconds, const char *unitName, int
// { // {
// min_count: <number> // optional, defaults to 10 // min_count: <number> // optional, defaults to 10
// } // }
Json::Value RPCHandler::doGetCounts(Json::Value jvRequest) Json::Value RPCHandler::doGetCounts(Json::Value jvRequest, int& cost)
{ {
int minCount = 10; int minCount = 10;
@@ -2022,7 +2025,7 @@ Json::Value RPCHandler::doGetCounts(Json::Value jvRequest)
int s = upTime(); int s = upTime();
textTime(uptime, s, "year", 365*24*60*60); textTime(uptime, s, "year", 365*24*60*60);
textTime(uptime, s, "day", 24*60*60); textTime(uptime, s, "day", 24*60*60);
textTime(uptime, s, "hour", 24*60); textTime(uptime, s, "hour", 60*60);
textTime(uptime, s, "minute", 60); textTime(uptime, s, "minute", 60);
textTime(uptime, s, "second", 1); textTime(uptime, s, "second", 1);
ret["uptime"] = uptime; ret["uptime"] = uptime;
@@ -2030,7 +2033,7 @@ Json::Value RPCHandler::doGetCounts(Json::Value jvRequest)
return ret; return ret;
} }
Json::Value RPCHandler::doLogLevel(Json::Value jvRequest) Json::Value RPCHandler::doLogLevel(Json::Value jvRequest, int& cost)
{ {
// log_level // log_level
if (!jvRequest.isMember("severity")) if (!jvRequest.isMember("severity"))
@@ -2078,7 +2081,7 @@ Json::Value RPCHandler::doLogLevel(Json::Value jvRequest)
// node: <domain>|<node_public>, // node: <domain>|<node_public>,
// comment: <comment> // optional // comment: <comment> // optional
// } // }
Json::Value RPCHandler::doUnlAdd(Json::Value jvRequest) Json::Value RPCHandler::doUnlAdd(Json::Value jvRequest, int& cost)
{ {
std::string strNode = jvRequest.isMember("node") ? jvRequest["node"].asString() : ""; std::string strNode = jvRequest.isMember("node") ? jvRequest["node"].asString() : "";
std::string strComment = jvRequest.isMember("comment") ? jvRequest["comment"].asString() : ""; std::string strComment = jvRequest.isMember("comment") ? jvRequest["comment"].asString() : "";
@@ -2102,7 +2105,7 @@ Json::Value RPCHandler::doUnlAdd(Json::Value jvRequest)
// { // {
// node: <domain>|<public_key> // node: <domain>|<public_key>
// } // }
Json::Value RPCHandler::doUnlDelete(Json::Value jvRequest) Json::Value RPCHandler::doUnlDelete(Json::Value jvRequest, int& cost)
{ {
if (!jvRequest.isMember("node")) if (!jvRequest.isMember("node"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -2125,7 +2128,7 @@ Json::Value RPCHandler::doUnlDelete(Json::Value jvRequest)
} }
} }
Json::Value RPCHandler::doUnlList(Json::Value) Json::Value RPCHandler::doUnlList(Json::Value, int& cost)
{ {
Json::Value obj(Json::objectValue); Json::Value obj(Json::objectValue);
@@ -2135,7 +2138,7 @@ Json::Value RPCHandler::doUnlList(Json::Value)
} }
// Populate the UNL from a local validators.txt file. // Populate the UNL from a local validators.txt file.
Json::Value RPCHandler::doUnlLoad(Json::Value) Json::Value RPCHandler::doUnlLoad(Json::Value, int& cost)
{ {
if (theConfig.VALIDATORS_FILE.empty() || !theApp->getUNL().nodeLoad(theConfig.VALIDATORS_FILE)) if (theConfig.VALIDATORS_FILE.empty() || !theApp->getUNL().nodeLoad(theConfig.VALIDATORS_FILE))
{ {
@@ -2147,7 +2150,7 @@ Json::Value RPCHandler::doUnlLoad(Json::Value)
// Populate the UNL from ripple.com's validators.txt file. // Populate the UNL from ripple.com's validators.txt file.
Json::Value RPCHandler::doUnlNetwork(Json::Value jvRequest) Json::Value RPCHandler::doUnlNetwork(Json::Value jvRequest, int& cost)
{ {
theApp->getUNL().nodeNetwork(); theApp->getUNL().nodeNetwork();
@@ -2155,7 +2158,7 @@ Json::Value RPCHandler::doUnlNetwork(Json::Value jvRequest)
} }
// unl_reset // unl_reset
Json::Value RPCHandler::doUnlReset(Json::Value jvRequest) Json::Value RPCHandler::doUnlReset(Json::Value jvRequest, int& cost)
{ {
theApp->getUNL().nodeReset(); theApp->getUNL().nodeReset();
@@ -2163,21 +2166,21 @@ Json::Value RPCHandler::doUnlReset(Json::Value jvRequest)
} }
// unl_score // unl_score
Json::Value RPCHandler::doUnlScore(Json::Value) Json::Value RPCHandler::doUnlScore(Json::Value, int& cost)
{ {
theApp->getUNL().nodeScore(); theApp->getUNL().nodeScore();
return "scoring requested"; return "scoring requested";
} }
Json::Value RPCHandler::doStop(Json::Value) Json::Value RPCHandler::doStop(Json::Value, int& cost)
{ {
theApp->stop(); theApp->stop();
return SYSTEM_NAME " server stopping"; return SYSTEM_NAME " server stopping";
} }
Json::Value RPCHandler::doLedgerAccept(Json::Value) Json::Value RPCHandler::doLedgerAccept(Json::Value, int& cost)
{ {
Json::Value jvResult; Json::Value jvResult;
@@ -2200,7 +2203,7 @@ Json::Value RPCHandler::doLedgerAccept(Json::Value)
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
// XXX In this case, not specify either ledger does not mean ledger current. It means any ledger. // XXX In this case, not specify either ledger does not mean ledger current. It means any ledger.
Json::Value RPCHandler::doTransactionEntry(Json::Value jvRequest) Json::Value RPCHandler::doTransactionEntry(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -2327,7 +2330,7 @@ Json::Value RPCHandler::lookupLedger(Json::Value jvRequest, Ledger::pointer& lpL
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// ... // ...
// } // }
Json::Value RPCHandler::doLedgerEntry(Json::Value jvRequest) Json::Value RPCHandler::doLedgerEntry(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -2534,7 +2537,7 @@ Json::Value RPCHandler::doLedgerEntry(Json::Value jvRequest)
// ledger_hash : <ledger> // ledger_hash : <ledger>
// ledger_index : <ledger_index> // ledger_index : <ledger_index>
// } // }
Json::Value RPCHandler::doLedgerHeader(Json::Value jvRequest) Json::Value RPCHandler::doLedgerHeader(Json::Value jvRequest, int& cost)
{ {
Ledger::pointer lpLedger; Ledger::pointer lpLedger;
Json::Value jvResult = lookupLedger(jvRequest, lpLedger); Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
@@ -2584,7 +2587,7 @@ rt_transactions
accounts accounts
rt_accounts rt_accounts
*/ */
Json::Value RPCHandler::doSubscribe(Json::Value jvRequest) Json::Value RPCHandler::doSubscribe(Json::Value jvRequest, int& cost)
{ {
InfoSub::pointer ispSub; InfoSub::pointer ispSub;
Json::Value jvResult(Json::objectValue); Json::Value jvResult(Json::objectValue);
@@ -2732,7 +2735,7 @@ Json::Value RPCHandler::doSubscribe(Json::Value jvRequest)
} }
// FIXME: This leaks RPCSub objects for JSON-RPC. Shouldn't matter for anyone sane. // FIXME: This leaks RPCSub objects for JSON-RPC. Shouldn't matter for anyone sane.
Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest) Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest, int& cost)
{ {
InfoSub::pointer ispSub; InfoSub::pointer ispSub;
Json::Value jvResult(Json::objectValue); Json::Value jvResult(Json::objectValue);
@@ -2845,8 +2848,10 @@ Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest)
// //
// JSON-RPC provides a method and an array of params. JSON-RPC is used as a transport for a command and a request object. The // JSON-RPC provides a method and an array of params. JSON-RPC is used as a transport for a command and a request object. The
// command is the method. The request object is supplied as the first element of the params. // command is the method. The request object is supplied as the first element of the params.
Json::Value RPCHandler::doRpcCommand(const std::string& strMethod, Json::Value& jvParams, int iRole) Json::Value RPCHandler::doRpcCommand(const std::string& strMethod, Json::Value& jvParams, int iRole, int& cost)
{ {
if (cost == 0)
cost = rpcCOST_DEFAULT;
cLog(lsTRACE) << "doRpcCommand:" << strMethod << ":" << jvParams; cLog(lsTRACE) << "doRpcCommand:" << strMethod << ":" << jvParams;
if (!jvParams.isArray() || jvParams.size() > 1) if (!jvParams.isArray() || jvParams.size() > 1)
@@ -2860,7 +2865,7 @@ Json::Value RPCHandler::doRpcCommand(const std::string& strMethod, Json::Value&
// Provide the JSON-RPC method as the field "command" in the request. // Provide the JSON-RPC method as the field "command" in the request.
jvRequest["command"] = strMethod; jvRequest["command"] = strMethod;
Json::Value jvResult = doCommand(jvRequest, iRole); Json::Value jvResult = doCommand(jvRequest, iRole, cost);
// Always report "status". On an error report the request as received. // Always report "status". On an error report the request as received.
if (jvResult.isMember("error")) if (jvResult.isMember("error"))
@@ -2875,15 +2880,17 @@ Json::Value RPCHandler::doRpcCommand(const std::string& strMethod, Json::Value&
return jvResult; return jvResult;
} }
Json::Value RPCHandler::doInternal(Json::Value jvRequest) Json::Value RPCHandler::doInternal(Json::Value jvRequest, int& cost)
{ // Used for debug or special-purpose RPC commands { // Used for debug or special-purpose RPC commands
if (!jvRequest.isMember("internal_command")) if (!jvRequest.isMember("internal_command"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
return RPCInternalHandler::runHandler(jvRequest["internal_command"].asString(), jvRequest["params"]); return RPCInternalHandler::runHandler(jvRequest["internal_command"].asString(), jvRequest["params"]);
} }
Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole) Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole, int &cost)
{ {
if (cost == 0)
cost = rpcCOST_DEFAULT;
if ((iRole != ADMIN) && (theApp->getJobQueue().getJobCountGE(jtCLIENT) > 500)) if ((iRole != ADMIN) && (theApp->getJobQueue().getJobCountGE(jtCLIENT) > 500))
return rpcError(rpcTOO_BUSY); return rpcError(rpcTOO_BUSY);
@@ -3002,7 +3009,7 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole)
else else
{ {
try { try {
Json::Value jvRaw = (this->*(commandsA[i].dfpFunc))(jvRequest); Json::Value jvRaw = (this->*(commandsA[i].dfpFunc))(jvRequest, cost);
// Regularize result. // Regularize result.
if (jvRaw.isObject()) if (jvRaw.isObject())
@@ -3023,6 +3030,8 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole)
catch (std::exception& e) catch (std::exception& e)
{ {
cLog(lsINFO) << "Caught throw: " << e.what(); cLog(lsINFO) << "Caught throw: " << e.what();
if (cost == rpcCOST_DEFAULT)
cost = rpcCOST_EXCEPTION;
return rpcError(rpcINTERNAL); return rpcError(rpcINTERNAL);
} }

View File

@@ -19,7 +19,7 @@ class RPCHandler
InfoSub::pointer mInfoSub; InfoSub::pointer mInfoSub;
int mRole; int mRole;
typedef Json::Value (RPCHandler::*doFuncPtr)(Json::Value params); typedef Json::Value (RPCHandler::*doFuncPtr)(Json::Value params, int& cost);
enum { enum {
optNone = 0, optNone = 0,
optNetwork = 1, // Need network optNetwork = 1, // Need network
@@ -43,71 +43,71 @@ class RPCHandler
Json::Value accountFromString(Ledger::ref lrLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex, const bool bStrict); Json::Value accountFromString(Ledger::ref lrLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex, const bool bStrict);
Json::Value doAccountInfo(Json::Value params); Json::Value doAccountInfo(Json::Value params, int& cost);
Json::Value doAccountLines(Json::Value params); Json::Value doAccountLines(Json::Value params, int& cost);
Json::Value doAccountOffers(Json::Value params); Json::Value doAccountOffers(Json::Value params, int& cost);
Json::Value doAccountTransactions(Json::Value params); Json::Value doAccountTransactions(Json::Value params, int& cost);
Json::Value doBookOffers(Json::Value params); Json::Value doBookOffers(Json::Value params, int& cost);
Json::Value doConnect(Json::Value params); Json::Value doConnect(Json::Value params, int& cost);
Json::Value doConsensusInfo(Json::Value params); Json::Value doConsensusInfo(Json::Value params, int& cost);
#if ENABLE_INSECURE #if ENABLE_INSECURE
Json::Value doDataDelete(Json::Value params); Json::Value doDataDelete(Json::Value params, int& cost);
Json::Value doDataFetch(Json::Value params); Json::Value doDataFetch(Json::Value params, int& cost);
Json::Value doDataStore(Json::Value params); Json::Value doDataStore(Json::Value params, int& cost);
#endif #endif
Json::Value doGetCounts(Json::Value params); Json::Value doGetCounts(Json::Value params, int& cost);
Json::Value doInternal(Json::Value params); Json::Value doInternal(Json::Value params, int& cost);
Json::Value doLedger(Json::Value params); Json::Value doLedger(Json::Value params, int& cost);
Json::Value doLogLevel(Json::Value params); Json::Value doLogLevel(Json::Value params, int& cost);
Json::Value doLogRotate(Json::Value params); Json::Value doLogRotate(Json::Value params, int& cost);
Json::Value doNicknameInfo(Json::Value params); Json::Value doNicknameInfo(Json::Value params, int& cost);
Json::Value doOwnerInfo(Json::Value params); Json::Value doOwnerInfo(Json::Value params, int& cost);
Json::Value doPeers(Json::Value params); Json::Value doPeers(Json::Value params, int& cost);
Json::Value doPing(Json::Value params); Json::Value doPing(Json::Value params, int& cost);
Json::Value doProfile(Json::Value params); Json::Value doProfile(Json::Value params, int& cost);
Json::Value doRandom(Json::Value jvRequest); Json::Value doRandom(Json::Value jvRequest, int& cost);
Json::Value doRipplePathFind(Json::Value jvRequest); Json::Value doRipplePathFind(Json::Value jvRequest, int& cost);
Json::Value doServerInfo(Json::Value params); // for humans Json::Value doServerInfo(Json::Value params, int& cost); // for humans
Json::Value doServerState(Json::Value params); // for machines Json::Value doServerState(Json::Value params, int& cost); // for machines
Json::Value doSessionClose(Json::Value params); Json::Value doSessionClose(Json::Value params, int& cost);
Json::Value doSessionOpen(Json::Value params); Json::Value doSessionOpen(Json::Value params, int& cost);
Json::Value doStop(Json::Value params); Json::Value doStop(Json::Value params, int& cost);
Json::Value doSign(Json::Value params); Json::Value doSign(Json::Value params, int& cost);
Json::Value doSubmit(Json::Value params); Json::Value doSubmit(Json::Value params, int& cost);
Json::Value doTx(Json::Value params); Json::Value doTx(Json::Value params, int& cost);
Json::Value doTxHistory(Json::Value params); Json::Value doTxHistory(Json::Value params, int& cost);
Json::Value doUnlAdd(Json::Value params); Json::Value doUnlAdd(Json::Value params, int& cost);
Json::Value doUnlDelete(Json::Value params); Json::Value doUnlDelete(Json::Value params, int& cost);
Json::Value doUnlFetch(Json::Value params); Json::Value doUnlFetch(Json::Value params, int& cost);
Json::Value doUnlList(Json::Value params); Json::Value doUnlList(Json::Value params, int& cost);
Json::Value doUnlLoad(Json::Value params); Json::Value doUnlLoad(Json::Value params, int& cost);
Json::Value doUnlNetwork(Json::Value params); Json::Value doUnlNetwork(Json::Value params, int& cost);
Json::Value doUnlReset(Json::Value params); Json::Value doUnlReset(Json::Value params, int& cost);
Json::Value doUnlScore(Json::Value params); Json::Value doUnlScore(Json::Value params, int& cost);
Json::Value doValidationCreate(Json::Value params); Json::Value doValidationCreate(Json::Value params, int& cost);
Json::Value doValidationSeed(Json::Value params); Json::Value doValidationSeed(Json::Value params, int& cost);
Json::Value doWalletAccounts(Json::Value params); Json::Value doWalletAccounts(Json::Value params, int& cost);
Json::Value doWalletLock(Json::Value params); Json::Value doWalletLock(Json::Value params, int& cost);
Json::Value doWalletPropose(Json::Value params); Json::Value doWalletPropose(Json::Value params, int& cost);
Json::Value doWalletSeed(Json::Value params); Json::Value doWalletSeed(Json::Value params, int& cost);
Json::Value doWalletUnlock(Json::Value params); Json::Value doWalletUnlock(Json::Value params, int& cost);
Json::Value doWalletVerify(Json::Value params); Json::Value doWalletVerify(Json::Value params, int& cost);
#if ENABLE_INSECURE #if ENABLE_INSECURE
Json::Value doLogin(Json::Value params); Json::Value doLogin(Json::Value params, int& cost);
#endif #endif
Json::Value doLedgerAccept(Json::Value params); Json::Value doLedgerAccept(Json::Value params, int& cost);
Json::Value doLedgerClosed(Json::Value params); Json::Value doLedgerClosed(Json::Value params, int& cost);
Json::Value doLedgerCurrent(Json::Value params); Json::Value doLedgerCurrent(Json::Value params, int& cost);
Json::Value doLedgerEntry(Json::Value params); Json::Value doLedgerEntry(Json::Value params, int& cost);
Json::Value doLedgerHeader(Json::Value params); Json::Value doLedgerHeader(Json::Value params, int& cost);
Json::Value doTransactionEntry(Json::Value params); Json::Value doTransactionEntry(Json::Value params, int& cost);
Json::Value doSubscribe(Json::Value params); Json::Value doSubscribe(Json::Value params, int& cost);
Json::Value doUnsubscribe(Json::Value params); Json::Value doUnsubscribe(Json::Value params, int& cost);
public: public:
@@ -116,8 +116,8 @@ public:
RPCHandler(NetworkOPs* netOps); RPCHandler(NetworkOPs* netOps);
RPCHandler(NetworkOPs* netOps, InfoSub::pointer infoSub); RPCHandler(NetworkOPs* netOps, InfoSub::pointer infoSub);
Json::Value doCommand(const Json::Value& jvRequest, int role); Json::Value doCommand(const Json::Value& jvRequest, int role, int& cost);
Json::Value doRpcCommand(const std::string& strCommand, Json::Value& jvParams, int iRole); Json::Value doRpcCommand(const std::string& strCommand, Json::Value& jvParams, int iRole, int& cost);
}; };
class RPCInternalHandler class RPCInternalHandler

View File

@@ -157,7 +157,8 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
RPCHandler mRPCHandler(mNetOps); RPCHandler mRPCHandler(mNetOps);
cLog(lsTRACE) << valParams; cLog(lsTRACE) << valParams;
Json::Value result = mRPCHandler.doRpcCommand(strMethod, valParams, mRole); int cost = 10;
Json::Value result = mRPCHandler.doRpcCommand(strMethod, valParams, mRole, cost);
cLog(lsTRACE) << result; cLog(lsTRACE) << result;
std::string strReply = JSONRPCReply(result, Json::Value(), id); std::string strReply = JSONRPCReply(result, Json::Value(), id);

View File

@@ -13,6 +13,7 @@
#include "NetworkOPs.h" #include "NetworkOPs.h"
#include "SerializedLedger.h" #include "SerializedLedger.h"
#include "RPCHandler.h" #include "RPCHandler.h"
#include "LoadManager.h"
class RPCServer : public boost::enable_shared_from_this<RPCServer> class RPCServer : public boost::enable_shared_from_this<RPCServer>
{ {

View File

@@ -1,7 +1,7 @@
// TODO: // TODO:
// - Do automatic bridging via XRP. // - Do automatic bridging via XRP.
// //
// OPTIMIZE: When calculating path increment, note if increment consumes all liquidity. No need to revesit path in the future if // OPTIMIZE: When calculating path increment, note if increment consumes all liquidity. No need to revisit path in the future if
// all liquidity is used. // all liquidity is used.
// //
@@ -270,7 +270,7 @@ TER PathState::pushNode(
// Insert intermediary issuer account if needed. // Insert intermediary issuer account if needed.
terResult = pushImply( terResult = pushImply(
ACCOUNT_XRP, // Rippling, but offer's don't have an account. ACCOUNT_XRP, // Rippling, but offers don't have an account.
pnPrv.uCurrencyID, pnPrv.uCurrencyID,
pnPrv.uIssuerID); pnPrv.uIssuerID);
} }
@@ -384,7 +384,7 @@ void PathState::setExpanded(
if (tesSUCCESS == terStatus if (tesSUCCESS == terStatus
&& !!uOutCurrencyID // Next is not XRP && !!uOutCurrencyID // Next is not XRP
&& uOutIssuerID != uReceiverID // Out issuer is not reciever && uOutIssuerID != uReceiverID // Out issuer is not receiver
&& (pnPrv.uCurrencyID != uOutCurrencyID // Previous will be an offer. && (pnPrv.uCurrencyID != uOutCurrencyID // Previous will be an offer.
|| pnPrv.uAccountID != uOutIssuerID)) // Need the implied issuer. || pnPrv.uAccountID != uOutIssuerID)) // Need the implied issuer.
{ {
@@ -491,7 +491,7 @@ void PathState::setCanonical(
uint160 uCurrencyID = uMaxCurrencyID; uint160 uCurrencyID = uMaxCurrencyID;
uint160 uIssuerID = uMaxIssuerID; uint160 uIssuerID = uMaxIssuerID;
// Node 0 is a composit of the sending account and saInAct. // Node 0 is a composite of the sending account and saInAct.
++uNode; // skip node 0 ++uNode; // skip node 0
// Last node is implied: Always skip last node // Last node is implied: Always skip last node
@@ -531,8 +531,7 @@ void PathState::setCanonical(
} }
else else
{ {
// Node 1 must be an account // Node 1 must be an account
} }
} }
else else
@@ -2983,7 +2982,7 @@ void TransactionEngine::calcOfferBridgeNext(
{ {
// Offer fully funded. // Offer fully funded.
// Account transfering funds in to offer always pays inbound fees. // Account transferring funds in to offer always pays inbound fees.
saOfferIn = saOfferGets; // XXX Add in fees? saOfferIn = saOfferGets; // XXX Add in fees?
@@ -3022,26 +3021,26 @@ void TransactionEngine::calcOfferBridgeNext(
// - reverse: prv is maximum to pay in (including fee) - cur is what is wanted: generally, minimizing prv // - reverse: prv is maximum to pay in (including fee) - cur is what is wanted: generally, minimizing prv
// - forward: prv is actual amount to pay in (including fee) - cur is what is wanted: generally, minimizing cur // - forward: prv is actual amount to pay in (including fee) - cur is what is wanted: generally, minimizing cur
// Value in is may be rippled or credited from limbo. Value out is put in limbo. // Value in is may be rippled or credited from limbo. Value out is put in limbo.
// If next is an offer, the amount needed is in cur reedem. // If next is an offer, the amount needed is in cur redeem.
// XXX What about account mentioned multiple times via offers? // XXX What about account mentioned multiple times via offers?
void TransactionEngine::calcNodeOffer( void TransactionEngine::calcNodeOffer(
bool bForward, bool bForward,
bool bMultiQuality, // True, if this is the only active path: we can do multiple qualities in this pass. bool bMultiQuality, // True, if this is the only active path: we can do multiple qualities in this pass.
const uint160& uPrvAccountID, // If 0, then funds from previous offer's limbo const uint160& uPrvAccountID, // If 0, then funds from previous offers limbo
const uint160& uPrvCurrencyID, const uint160& uPrvCurrencyID,
const uint160& uPrvIssuerID, const uint160& uPrvIssuerID,
const uint160& uCurCurrencyID, const uint160& uCurCurrencyID,
const uint160& uCurIssuerID, const uint160& uCurIssuerID,
const STAmount& uPrvRedeemReq, // --> In limit. const STAmount& uPrvRedeemReq, // --> In limit.
STAmount& uPrvRedeemAct, // <-> In limit achived. STAmount& uPrvRedeemAct, // <-> In limit achieved.
const STAmount& uCurRedeemReq, // --> Out limit. Driver when uCurIssuerID == uNxtIssuerID (offer would redeem to next) const STAmount& uCurRedeemReq, // --> Out limit. Driver when uCurIssuerID == uNxtIssuerID (offer would redeem to next)
STAmount& uCurRedeemAct, // <-> Out limit achived. STAmount& uCurRedeemAct, // <-> Out limit achieved.
const STAmount& uCurIssueReq, // --> In limit. const STAmount& uCurIssueReq, // --> In limit.
STAmount& uCurIssueAct, // <-> In limit achived. STAmount& uCurIssueAct, // <-> In limit achieved.
const STAmount& uCurIssueReq, // --> Out limit. Driver when uCurIssueReq != uNxtIssuerID (offer would effectively issue or transfer to next) const STAmount& uCurIssueReq, // --> Out limit. Driver when uCurIssueReq != uNxtIssuerID (offer would effectively issue or transfer to next)
STAmount& uCurIssueAct, // <-> Out limit achived. STAmount& uCurIssueAct, // <-> Out limit achieved.
STAmount& saPay, STAmount& saPay,
STAmount& saGot STAmount& saGot
@@ -3095,13 +3094,13 @@ void TransactionEngine::calcNodeOffer(
bool bRedeeming = false; bool bRedeeming = false;
bool bIssuing = false; bool bIssuing = false;
// The price varies as we change between issuing and transfering, so unless bMultiQuality, we must stick with a mode once it // The price varies as we change between issuing and transferring, so unless bMultiQuality, we must stick with a mode once it
// is determined. // is determined.
if (bBridge && (bInNext || bOutNext)) if (bBridge && (bInNext || bOutNext))
{ {
// Bridging and need to calculate next bridge rate. // Bridging and need to calculate next bridge rate.
// A bridge can consist of multiple offers. As offer's are consumed, the effective rate changes. // A bridge can consist of multiple offers. As offers are consumed, the effective rate changes.
if (bInNext) if (bInNext)
{ {

View File

@@ -14,6 +14,7 @@
#include "CallRPC.h" #include "CallRPC.h"
#include "InstanceCounter.h" #include "InstanceCounter.h"
#include "Log.h" #include "Log.h"
#include "LoadManager.h"
#include "RPCErr.h" #include "RPCErr.h"
DEFINE_INSTANCE(WebSocketConnection); DEFINE_INSTANCE(WebSocketConnection);
@@ -45,6 +46,7 @@ protected:
weak_connection_ptr mConnection; weak_connection_ptr mConnection;
NetworkOPs& mNetwork; NetworkOPs& mNetwork;
std::string mRemoteIP; std::string mRemoteIP;
LoadSource mLoadSource;
boost::asio::deadline_timer mPingTimer; boost::asio::deadline_timer mPingTimer;
bool mPinged; bool mPinged;
@@ -56,9 +58,9 @@ public:
WSConnection(WSServerHandler<endpoint_type>* wshpHandler, const connection_ptr& cpConnection) WSConnection(WSServerHandler<endpoint_type>* wshpHandler, const connection_ptr& cpConnection)
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()), : mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()),
mPingTimer(cpConnection->get_io_service()), mPinged(false) mRemoteIP(cpConnection->get_socket().lowest_layer().remote_endpoint().address().to_string()),
mLoadSource(mRemoteIP), mPingTimer(cpConnection->get_io_service()), mPinged(false)
{ {
mRemoteIP = cpConnection->get_socket().lowest_layer().remote_endpoint().address().to_string();
cLog(lsDEBUG) << "Websocket connection from " << mRemoteIP; cLog(lsDEBUG) << "Websocket connection from " << mRemoteIP;
setPingTimer(); setPingTimer();
} }
@@ -86,6 +88,14 @@ public:
// Utilities // Utilities
Json::Value invokeCommand(Json::Value& jvRequest) Json::Value invokeCommand(Json::Value& jvRequest)
{ {
if (theApp->getLoadManager().shouldCutoff(mLoadSource))
{
connection_ptr ptr = mConnection.lock();
if (ptr)
ptr->close(websocketpp::close::status::PROTOCOL_ERROR, "overload");
return rpcError(rpcTOO_BUSY);
}
if (!jvRequest.isMember("command")) if (!jvRequest.isMember("command"))
{ {
Json::Value jvResult(Json::objectValue); Json::Value jvResult(Json::objectValue);
@@ -100,9 +110,11 @@ public:
jvResult["id"] = jvRequest["id"]; jvResult["id"] = jvRequest["id"];
} }
theApp->getLoadManager().adjust(mLoadSource, 5);
return jvResult; return jvResult;
} }
int cost = 10;
RPCHandler mRPCHandler(&mNetwork, boost::shared_polymorphic_downcast<InfoSub>(this->shared_from_this())); RPCHandler mRPCHandler(&mNetwork, boost::shared_polymorphic_downcast<InfoSub>(this->shared_from_this()));
Json::Value jvResult(Json::objectValue); Json::Value jvResult(Json::objectValue);
@@ -116,9 +128,12 @@ public:
} }
else else
{ {
jvResult["result"] = mRPCHandler.doCommand(jvRequest, iRole); jvResult["result"] = mRPCHandler.doCommand(jvRequest, iRole, cost);
} }
if (theApp->getLoadManager().adjust(mLoadSource, cost) && theApp->getLoadManager().shouldWarn(mLoadSource))
jvResult["warning"] = "load";
// Currently we will simply unwrap errors returned by the RPC // Currently we will simply unwrap errors returned by the RPC
// API, in the future maybe we can make the responses // API, in the future maybe we can make the responses
// consistent. // consistent.

View File

@@ -45,7 +45,8 @@ void startServer()
RPCHandler rhHandler(&theApp->getOPs()); RPCHandler rhHandler(&theApp->getOPs());
Json::Value jvResult = rhHandler.doCommand(jvCommand, RPCHandler::ADMIN); int cost = 10;
Json::Value jvResult = rhHandler.doCommand(jvCommand, RPCHandler::ADMIN, cost);
if (!theConfig.QUIET) if (!theConfig.QUIET)
std::cerr << "Result: " << jvResult << std::endl; std::cerr << "Result: " << jvResult << std::endl;