diff --git a/newcoin.vcxproj b/newcoin.vcxproj
index 83c3483ef..b5839160e 100644
--- a/newcoin.vcxproj
+++ b/newcoin.vcxproj
@@ -125,6 +125,7 @@
+
@@ -183,7 +184,6 @@
-
diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters
index f7dfc590e..25533c2dc 100644
--- a/newcoin.vcxproj.filters
+++ b/newcoin.vcxproj.filters
@@ -276,9 +276,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -360,6 +357,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/cpp/ripple/Application.h b/src/cpp/ripple/Application.h
index a7518299e..4a2b16e91 100644
--- a/src/cpp/ripple/Application.h
+++ b/src/cpp/ripple/Application.h
@@ -3,6 +3,8 @@
#include
+#include "../database/database.h"
+
#include "LedgerMaster.h"
#include "UniqueNodeList.h"
#include "ConnectionPool.h"
@@ -17,9 +19,10 @@
#include "ValidationCollection.h"
#include "Suppression.h"
#include "SNTPClient.h"
-#include "../database/database.h"
#include "JobQueue.h"
#include "RPCHandler.h"
+#include "ProofOfWork.h"
+#include "LoadManager.h"
class RPCDoor;
class PeerDoor;
@@ -58,6 +61,8 @@ class Application
SNTPClient mSNTPClient;
JobQueue mJobQueue;
RPCHandler mRPCHandler;
+ ProofOfWorkGenerator mPOWGen;
+ LoadManager mLoadMgr;
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
@@ -102,6 +107,8 @@ public:
SuppressionTable& getSuppression() { return mSuppressions; }
RPCHandler& getRPCHandler() { return mRPCHandler; }
boost::recursive_mutex& getMasterLock() { return mMasterLock; }
+ ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
+ LoadManager& getLoadManager() { return mLoadMgr; }
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp
index 0b040c5ad..adac5d0b3 100644
--- a/src/cpp/ripple/LoadManager.cpp
+++ b/src/cpp/ripple/LoadManager.cpp
@@ -1,5 +1,22 @@
#include "LoadManager.h"
+LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int debitLimit) :
+ mCreditRate(creditRate), mCreditLimit(creditLimit), mDebitWarn(debitWarn), mDebitLimit(debitLimit), mCosts(LT_MAX)
+{
+ addLoadCost(LoadCost(LT_InvalidRequest, 10, LC_CPU | LC_Network));
+ addLoadCost(LoadCost(LT_RequestNoReply, 1, LC_CPU | LC_Disk));
+ addLoadCost(LoadCost(LT_InvalidSignature, 100, LC_CPU));
+ addLoadCost(LoadCost(LT_UnwantedData, 5, LC_CPU | LC_Network));
+
+ addLoadCost(LoadCost(LT_NewTrusted, 10, 0));
+ addLoadCost(LoadCost(LT_NewTransaction, 2, 0));
+ addLoadCost(LoadCost(LT_NeededData, 10, 0));
+
+ addLoadCost(LoadCost(LT_RequestData, 5, LC_Disk | LC_Network));
+ addLoadCost(LoadCost(LT_CheapQuery, 1, LC_CPU));
+}
+
+
int LoadManager::getCreditRate() const
{
boost::mutex::scoped_lock sl(mLock);
@@ -84,6 +101,12 @@ bool LoadManager::shouldCutoff(LoadSource& source) const
return !source.isPrivileged() && (source.mBalance < mDebitLimit);
}
+bool LoadManager::adjust(LoadSource& source, LoadType t) const
+{ // FIXME: Scale by category
+ LoadCost cost = mCosts[static_cast(t)];
+ return adjust(source, cost.mCost);
+}
+
bool LoadManager::adjust(LoadSource& source, int credits) const
{ // return: true = need to warn/cutoff
time_t now = time(NULL);
diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h
index 08478e140..a48166577 100644
--- a/src/cpp/ripple/LoadManager.h
+++ b/src/cpp/ripple/LoadManager.h
@@ -1,10 +1,50 @@
#ifndef LOADSOURCE__H
#define LOADSOURCE__H
+#include
+
#include
#include "types.h"
+enum LoadType
+{ // types of load that can be placed on the server
+
+ // Bad things
+ LT_InvalidRequest, // A request that we can immediately tell is invalid
+ LT_RequestNoReply, // A request that we cannot satisfy
+ LT_InvalidSignature, // An object whose signature we had to check and it failed
+ LT_UnwantedData, // Data we have no use for
+ LT_BadPoW, // Proof of work not valid
+
+ // Good things
+ LT_NewTrusted, // A new transaction/validation/proposal we trust
+ LT_NewTransaction, // A new, valid transaction
+ LT_NeededData, // Data we requested
+
+ // Requests
+ LT_RequestData, // A request that is hard to satisfy, disk access
+ LT_CheapQuery, // A query that is trivial, cached data
+
+ LT_MAX = LT_CheapQuery
+};
+
+// load categoryies
+static const int LC_Disk = 1;
+static const int LC_CPU = 2;
+static const int LC_Network = 4;
+
+class LoadCost
+{
+public:
+ LoadType mType;
+ int mCost;
+ int mCategories;
+
+ LoadCost() : mType(), mCost(0), mCategories(0) { ; }
+ LoadCost(LoadType t, int cost, int cat) : mType(t), mCost(cost), mCategories(cat) { ; }
+};
+
class LoadSource
{ // a single endpoint that can impose load
friend class LoadManager;
@@ -40,17 +80,20 @@ protected:
int mCreditRate; // credits gained/lost per second
int mCreditLimit; // the most credits a source can have
- int mDebitWarn; // when a source drops below this, we warn
+ int mDebitWarn; // when a source drops below this, we warn
int mDebitLimit; // when a source drops below this, we cut it off (should be negative)
mutable boost::mutex mLock;
void canonicalize(LoadSource&, const time_t now) const;
+ std::vector mCosts;
+
+ void addLoadCost(const LoadCost& c) { mCosts[static_cast(c.mType)] = c; }
+
public:
- LoadManager(int creditRate, int creditLimit, int debitWarn, int debitLimit) :
- mCreditRate(creditRate), mCreditLimit(creditLimit), mDebitWarn(debitWarn), mDebitLimit(debitLimit) { ; }
+ LoadManager(int creditRate = 10, int creditLimit = 50, int debitWarn = -50, int debitLimit = -100);
int getCreditRate() const;
int getCreditLimit() const;
@@ -64,6 +107,9 @@ public:
bool shouldWarn(LoadSource&) const;
bool shouldCutoff(LoadSource&) const;
bool adjust(LoadSource&, int credits) const; // return value: false=balance okay, true=warn/cutoff
+ bool adjust(LoadSource&, LoadType l) const;
+
+ int getCost(LoadType t) { return mCosts[static_cast(t)].mCost; }
};
class LoadFeeTrack
diff --git a/src/cpp/ripple/LoadTypes.h b/src/cpp/ripple/LoadTypes.h
deleted file mode 100644
index a2232174c..000000000
--- a/src/cpp/ripple/LoadTypes.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef LOADTYPES__H
-#define LOADTYPES__H
-
-enum LoadType
-{ // types of load that can be placed on the server
-
- // Bad things
- LT_InvalidRequest, // A request that we can immediately tell is invalid
- LT_RequestNoReply, // A request that we cannot satisfy
- LT_InvalidSignature, // An object whose signature we had to check and it failed
- LT_UnwantedData, // Data we have no use for
-
- // Good things
- LT_NewTrusted, // A new transaction/validation/proposal we trust
- LT_NewTransaction, // A new, valid transaction
- LT_NeededData, // Data we requested
-
- // Requests
- LT_RequestData, // A request that is hard to satisfy, disk access
- LT_CheapQuery, // A query that is trivial, cached data
-};
-
-static const int LoadCategoryDisk = 1;
-static const int LoadCategoryCPU = 2;
-static const int LoadCateogryNetwork = 4;
-
-#endif
diff --git a/src/cpp/ripple/Offer.cpp b/src/cpp/ripple/Offer.cpp
index 0b9407b32..5fe7add9f 100644
--- a/src/cpp/ripple/Offer.cpp
+++ b/src/cpp/ripple/Offer.cpp
@@ -12,4 +12,5 @@ Offer::Offer(SerializedLedgerEntry::pointer ledgerEntry) : AccountItem(ledgerEnt
mAccount=mLedgerEntry->getFieldAccount(sfAccount);
mTakerGets = mLedgerEntry->getFieldAmount(sfTakerGets);
mTakerPays = mLedgerEntry->getFieldAmount(sfTakerPays);
+ mSeq = mLedgerEntry->getFieldU32(sfSequence);
}
\ No newline at end of file
diff --git a/src/cpp/ripple/Offer.h b/src/cpp/ripple/Offer.h
index 815cfde09..75cc5dc57 100644
--- a/src/cpp/ripple/Offer.h
+++ b/src/cpp/ripple/Offer.h
@@ -6,6 +6,7 @@ class Offer : public AccountItem
RippleAddress mAccount;
STAmount mTakerGets;
STAmount mTakerPays;
+ int mSeq;
Offer(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger
@@ -17,5 +18,6 @@ public:
STAmount getTakerPays(){ return(mTakerPays); }
STAmount getTakerGets(){ return(mTakerGets); }
RippleAddress getAccount(){ return(mAccount); }
+ int getSeq(){ return(mSeq); }
};
\ No newline at end of file
diff --git a/src/cpp/ripple/ParameterTable.cpp b/src/cpp/ripple/ParameterTable.cpp
new file mode 100644
index 000000000..cb61a064b
--- /dev/null
+++ b/src/cpp/ripple/ParameterTable.cpp
@@ -0,0 +1,159 @@
+#include "ParameterTable.h"
+
+#include
+#include
+
+#include "utils.h"
+
+bool ParameterNode::setValue(const std::string& name, const Json::Value& value, Json::Value& error)
+{
+ if (name.empty()) // this node
+ return setValue(value, error);
+
+ size_t dot = name.find('.');
+ if (dot == std::string::npos) // a child of this node
+ {
+ std::map::iterator it = mChildren.find(name);
+ if (it == mChildren.end())
+ {
+ error = Json::objectValue;
+ error["error"] = "Name not found";
+ error["name"] = name;
+ return false;
+ }
+ return it->second->setValue(value, error);
+ }
+
+ std::map::iterator it = mChildren.find(name.substr(0, dot));
+ if (it == mChildren.end())
+ {
+ error = Json::objectValue;
+ error["error"] = "Name not found";
+ error["name"] = name;
+ return false;
+ }
+
+ ParameterNode* n = dynamic_cast(it->second.get());
+ if (!n)
+ {
+ error = Json::objectValue;
+ error["error"] = "Node has no children";
+ error["name"] = it->second->getName();
+ }
+
+ return n->setValue(name.substr(dot + 1), value, error);
+}
+
+bool ParameterNode::addNode(const std::string& name, Parameter::ref node)
+{
+ if (name.empty()) // this node
+ return false;
+
+ size_t dot = name.find('.');
+ if (dot == std::string::npos) // a child of this node
+ {
+ std::map::iterator it = mChildren.find(name);
+ if (it != mChildren.end())
+ return false;
+ mChildren[name] = node;
+ return true;
+ }
+
+ std::map::iterator it = mChildren.find(name.substr(0, dot));
+ ParameterNode* n;
+ if (it == mChildren.end())
+ { // create a new inner node
+ ParameterNode::pointer node = boost::make_shared(getShared(), name.substr(0, dot));
+ n = dynamic_cast(node.get());
+ assert(n);
+ mChildren[name] = node;
+ }
+ else
+ { // existing node passed through must be inner
+ ParameterNode* n = dynamic_cast(it->second.get());
+ if (!n)
+ return false;
+ }
+
+ return n->addNode(name.substr(dot + 1), node);
+}
+
+Json::Value ParameterNode::getValue(int i) const
+{
+ Json::Value v(Json::objectValue);
+ typedef std::pair string_ref_pair;
+ BOOST_FOREACH(const string_ref_pair& it, mChildren)
+ {
+ v[it.first] = it.second->getValue(i);
+ }
+ return v;
+}
+
+bool ParameterNode::setValue(const Json::Value& value, Json::Value& error)
+{
+ error = Json::objectValue;
+ error["error"] = "Cannot end on an inner node";
+
+ Json::Value nodes(Json::arrayValue);
+ typedef std::pair string_ref_pair;
+ BOOST_FOREACH(const string_ref_pair& it, mChildren)
+ {
+ nodes.append(it.first);
+ }
+ error["legal_nodes"] = nodes;
+ return false;
+}
+
+ParameterString::ParameterString(Parameter::ref parent, const std::string& name, const std::string& value)
+ : Parameter(parent, name), mValue(value)
+{ ; }
+
+Json::Value ParameterString::getValue(int) const
+{
+ return Json::Value(mValue);
+}
+
+bool ParameterString::setValue(const Json::Value& value, Json::Value& error)
+{
+ if (!value.isConvertibleTo(Json::stringValue))
+ {
+ error = Json::objectValue;
+ error["error"] = "Cannot convert to string";
+ error["value"] = value;
+ return false;
+ }
+ mValue = value.asString();
+ return true;
+}
+
+ParameterInt::ParameterInt(Parameter::ref parent, const std::string& name, int value)
+ : Parameter(parent, name), mValue(value)
+{ ; }
+
+Json::Value ParameterInt::getValue(int) const
+{
+ return Json::Value(mValue);
+}
+
+bool ParameterInt::setValue(const Json::Value& value, Json::Value& error)
+{
+ if (value.isConvertibleTo(Json::intValue))
+ {
+ mValue = value.asInt();
+ return true;
+ }
+ if (value.isConvertibleTo(Json::stringValue))
+ {
+ try
+ {
+ mValue = lexical_cast_st(value.asString());
+ }
+ catch (...)
+ {
+ }
+ }
+ error = Json::objectValue;
+ error["error"] = "Cannot convert to integer";
+ error["value"] = value;
+ return false;
+}
diff --git a/src/cpp/ripple/ParameterTable.h b/src/cpp/ripple/ParameterTable.h
new file mode 100644
index 000000000..897a8551f
--- /dev/null
+++ b/src/cpp/ripple/ParameterTable.h
@@ -0,0 +1,72 @@
+#ifndef PARAMETER_TABLE__H
+#define PARAMETER_TABLE__H
+
+#include
+#include