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 + +#include +#include + +#include "../json/value.h" + +class Parameter : public boost::enable_shared_from_this +{ // abstract base class parameters are derived from +public: + typedef boost::shared_ptr pointer; + typedef const boost::shared_ptr& ref; + +protected: + pointer mParent; + std::string mName; + +public: + Parameter(Parameter::ref parent, const std::string& name) : mParent(parent), mName(name) { ; } + virtual ~Parameter() { ; } + + const std::string& getName() const { return mName; } + + virtual Json::Value getValue(int) const = 0; + virtual bool setValue(const Json::Value& value, Json::Value& error) = 0; + + Parameter::pointer getShared() { return shared_from_this(); } +}; + +class ParameterNode : public Parameter +{ +protected: + std::map mChildren; + +public: + ParameterNode(Parameter::ref parent, const std::string& name) : Parameter(parent, name) { ; } + bool addChildNode(Parameter::ref node); + + bool setValue(const std::string& name, const Json::Value& value, Json::Value& error); + bool addNode(const std::string& name, Parameter::ref node); + + virtual Json::Value getValue(int) const; + virtual bool setValue(const Json::Value& value, Json::Value& error); +}; + +class ParameterString : public Parameter +{ +protected: + std::string mValue; + +public: + ParameterString(Parameter::ref parent, const std::string& name, const std::string& value); + virtual Json::Value getValue(int) const; + virtual bool setValue(const Json::Value& value, Json::Value& error); +}; + +class ParameterInt : public Parameter +{ +protected: + int mValue; + +public: + ParameterInt(Parameter::ref parent, const std::string& name, int value); + virtual Json::Value getValue(int) const; + virtual bool setValue(const Json::Value& value, Json::Value& error); +}; + +#endif diff --git a/src/cpp/ripple/Peer.cpp b/src/cpp/ripple/Peer.cpp index b35af8d0e..571246206 100644 --- a/src/cpp/ripple/Peer.cpp +++ b/src/cpp/ripple/Peer.cpp @@ -600,11 +600,11 @@ void Peer::processReadBuffer() } } -void Peer::punishPeer(const boost::weak_ptr& wp, PeerPunish pp) +void Peer::punishPeer(const boost::weak_ptr& wp, LoadType l) { Peer::pointer p = wp.lock(); if (p) - p->punishPeer(pp); + p->punishPeer(l); } void Peer::recvHello(ripple::TMHello& packet) @@ -743,7 +743,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx if (tx->getStatus() == INVALID) { theApp->getSuppression().setFlag(stx->getTransactionID(), SF_BAD); - Peer::punishPeer(peer, PP_BAD_SIGNATURE); + Peer::punishPeer(peer, LT_InvalidSignature); return; } else @@ -759,7 +759,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx catch (...) { theApp->getSuppression().setFlags(stx->getTransactionID(), SF_BAD); - punishPeer(peer, PP_INVALID_REQUEST); + punishPeer(peer, LT_InvalidRequest); } #endif } @@ -783,7 +783,7 @@ void Peer::recvTransaction(ripple::TMTransaction& packet) { // we have seen this transaction recently if ((flags & SF_BAD) != 0) { - punishPeer(PP_BAD_SIGNATURE); + punishPeer(LT_InvalidSignature); return; } @@ -828,7 +828,7 @@ static void checkPropose(Job& job, boost::shared_ptr packe if (!proposal->checkSign(set.signature())) { cLog(lsWARNING) << "proposal with previous ledger fails signature check"; - Peer::punishPeer(peer, PP_BAD_SIGNATURE); + Peer::punishPeer(peer, LT_InvalidSignature); return; } else @@ -874,14 +874,14 @@ void Peer::recvPropose(const boost::shared_ptr& packet) (set.signature().size() < 56) || (set.nodepubkey().size() > 128) || (set.signature().size() > 128)) { cLog(lsWARNING) << "Received proposal is malformed"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidSignature); return; } if (set.has_previousledger() && (set.previousledger().size() != 32)) { cLog(lsWARNING) << "Received proposal is malformed"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } @@ -930,7 +930,7 @@ void Peer::recvHaveTxSet(ripple::TMHaveTransactionSet& packet) uint256 hashes; if (packet.hash().size() != (256 / 8)) { - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } uint256 hash; @@ -938,7 +938,7 @@ void Peer::recvHaveTxSet(ripple::TMHaveTransactionSet& packet) if (packet.status() == ripple::tsHAVE) addTxSet(hash); if (!theApp->getOPs().hasTXSet(shared_from_this(), hash, packet.status())) - punishPeer(PP_UNWANTED_DATA); + punishPeer(LT_UnwantedData); } static void checkValidation(Job&, SerializedValidation::pointer val, uint256 signingHash, @@ -951,7 +951,7 @@ static void checkValidation(Job&, SerializedValidation::pointer val, uint256 sig if (!val->isValid(signingHash)) { cLog(lsWARNING) << "Validation is invalid"; - Peer::punishPeer(peer, PP_UNKNOWN_REQUEST); + Peer::punishPeer(peer, LT_InvalidRequest); return; } @@ -966,7 +966,7 @@ static void checkValidation(Job&, SerializedValidation::pointer val, uint256 sig catch (...) { cLog(lsWARNING) << "Exception processing validation"; - Peer::punishPeer(peer, PP_UNKNOWN_REQUEST); + Peer::punishPeer(peer, LT_InvalidRequest); } #endif } @@ -976,7 +976,7 @@ void Peer::recvValidation(const boost::shared_ptr& packet) if (packet->validation().size() < 50) { cLog(lsWARNING) << "Too small validation from peer"; - punishPeer(PP_UNKNOWN_REQUEST); + punishPeer(LT_InvalidRequest); return; } @@ -1004,7 +1004,7 @@ void Peer::recvValidation(const boost::shared_ptr& packet) catch (...) { cLog(lsWARNING) << "Exception processing validation"; - punishPeer(PP_UNKNOWN_REQUEST); + punishPeer(LT_InvalidRequest); } #endif } @@ -1138,10 +1138,32 @@ void Peer::recvAccount(ripple::TMAccount& packet) void Peer::recvProofWork(ripple::TMProofWork& packet) { + if (packet.has_response()) + { // this is an answer to a proof of work we requested + if (packet.response().size() != (256 / 8)) + { + punishPeer(LT_InvalidRequest); + return; + } + uint256 response; + memcpy(response.begin(), packet.response().data(), 256 / 8); + POWResult r = theApp->getPowGen().checkProof(packet.token(), response); + if (r == powOK) + { + // credit peer + // WRITEME + return; + } + // return error message + // WRITEME + if (r != powTOOEASY) + punishPeer(LT_BadPoW); + return; + } + if (packet.has_result()) { // this is a reply to a proof of work we sent // WRITEME - return; } if (packet.has_target() && packet.has_challenge() && packet.has_iterations()) @@ -1151,7 +1173,7 @@ void Peer::recvProofWork(ripple::TMProofWork& packet) uint256 challenge, target; if ((packet.challenge().size() != (256 / 8)) || (packet.target().size() != (256 / 8))) { - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } memcpy(challenge.begin(), packet.challenge().data(), 256 / 8); @@ -1160,7 +1182,7 @@ void Peer::recvProofWork(ripple::TMProofWork& packet) challenge, target); if (!pow->isValid()) { - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } @@ -1232,7 +1254,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet) cLog(lsINFO) << "Received request for TX candidate set data " << getIP(); if ((!packet.has_ledgerhash() || packet.ledgerhash().size() != 32)) { - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); cLog(lsWARNING) << "invalid request"; return; } @@ -1263,7 +1285,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet) return; } cLog(lsERROR) << "We do not have the map our peer wants"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } reply.set_ledgerseq(0); @@ -1281,7 +1303,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet) uint256 ledgerhash; if (packet.ledgerhash().size() != 32) { - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); cLog(lsWARNING) << "Invalid request"; return; } @@ -1326,14 +1348,14 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet) } else { - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); cLog(lsWARNING) << "Can't figure out what ledger they want"; return; } if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq() != ledger->getLedgerSeq()))) { - punishPeer(PP_UNKNOWN_REQUEST); + punishPeer(LT_InvalidRequest); if (sLog(lsWARNING)) { if (ledger) @@ -1391,7 +1413,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet) if ((!map) || (packet.nodeids_size() == 0)) { cLog(lsWARNING) << "Can't find map or empty request"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } @@ -1401,7 +1423,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet) if(!mn.isValid()) { cLog(lsWARNING) << "Request for invalid node"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } std::vector nodeIDs; @@ -1434,7 +1456,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet) if (packet.nodes().size() <= 0) { cLog(lsWARNING) << "Ledger/TXset data with no nodes"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } @@ -1449,7 +1471,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet) else { cLog(lsINFO) << "Unable to route TX/ledger data reply"; - punishPeer(PP_UNWANTED_DATA); + punishPeer(LT_UnwantedData); } return; } @@ -1460,7 +1482,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet) if(packet.ledgerhash().size() != 32) { cLog(lsWARNING) << "TX candidate reply with invalid hash size"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } memcpy(hash.begin(), packet.ledgerhash().data(), 32); @@ -1475,7 +1497,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet) if (!node.has_nodeid() || !node.has_nodedata() || (node.nodeid().size() != 33)) { cLog(lsWARNING) << "LedgerData request with invalid node ID"; - punishPeer(PP_INVALID_REQUEST); + punishPeer(LT_InvalidRequest); return; } nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size())); @@ -1483,13 +1505,13 @@ void Peer::recvLedger(ripple::TMLedgerData& packet) } SMAddNode san = theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData); if (san.isInvalid()) - punishPeer(PP_UNWANTED_DATA); + punishPeer(LT_UnwantedData); return; } SMAddNode san = theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()); if (san.isInvalid()) - punishPeer(PP_UNWANTED_DATA); + punishPeer(LT_UnwantedData); } bool Peer::hasLedger(const uint256& hash) const @@ -1603,8 +1625,12 @@ void Peer::sendGetPeers() sendPacket(packet); } -void Peer::punishPeer(PeerPunish) +void Peer::punishPeer(LoadType l) { + if (theApp->getLoadManager().adjust(mLoad, l)) + { + // WRITEME + } } void Peer::doProofOfWork(Job&, boost::weak_ptr peer, ProofOfWork::pointer pow) diff --git a/src/cpp/ripple/Peer.h b/src/cpp/ripple/Peer.h index df1dceee3..79a20649f 100644 --- a/src/cpp/ripple/Peer.h +++ b/src/cpp/ripple/Peer.h @@ -15,22 +15,7 @@ #include "InstanceCounter.h" #include "JobQueue.h" #include "ProofOfWork.h" - -enum PeerPunish -{ - PP_INVALID_REQUEST = 1, // The peer sent a request that makes no sense - PP_UNKNOWN_REQUEST = 2, // The peer sent a request that might be garbage - PP_UNWANTED_DATA = 3, // The peer sent us data we didn't want/need - PP_BAD_SIGNATURE = 4, // Object had bad signature -}; - -enum PeerReward -{ - PR_NEEDED_DATA = 1, // The peer gave us some data we needed - PR_NEW_TRANSACTION = 2, // The peer gave us a new transaction - PR_FIRST_USEFUL = 3, // The peer was first to give us something like a trusted proposal - PR_USEFUL = 4 // The peer gave us a trusted proposal, just not quite first -}; +#include "LoadManager.h" typedef std::pair ipPort; @@ -57,6 +42,7 @@ private: uint256 mCookieHash; uint64 mPeerId; bool mPrivate; // Keep peer IP private. + LoadSource mLoad; uint256 mClosedLedgerHash, mPreviousLedgerHash; std::list mRecentLedgers; @@ -151,8 +137,8 @@ public: void sendGetFullLedger(uint256& hash); void sendGetPeers(); - void punishPeer(PeerPunish pp); - static void punishPeer(const boost::weak_ptr&, PeerPunish); + void punishPeer(LoadType); + static void punishPeer(const boost::weak_ptr&, LoadType); Json::Value getJson(); bool isConnected() const { return mHelloed && !mDetaching; } diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index ad53e90aa..c2fa4648d 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -643,6 +643,7 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest) //obj["account"] = account.humanAccountID(); obj["taker_pays"] = takerPays.getJson(0); obj["taker_gets"] = takerGets.getJson(0); + obj["seq"] = offer->getSeq(); jsonLines.append(obj); } diff --git a/src/cpp/ripple/WSDoor.cpp b/src/cpp/ripple/WSDoor.cpp index f5327a486..4213487cd 100644 --- a/src/cpp/ripple/WSDoor.cpp +++ b/src/cpp/ripple/WSDoor.cpp @@ -66,9 +66,28 @@ void WSDoor::startListening() // mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL); // Call the main-event-loop of the websocket server. - mSEndpoint->listen( - boost::asio::ip::tcp::endpoint( - boost::asio::ip::address().from_string(mIp), mPort)); + try + { + mSEndpoint->listen( + boost::asio::ip::tcp::endpoint( + boost::asio::ip::address().from_string(mIp), mPort)); + } + catch (websocketpp::exception& e) + { + Log(lsWARNING) << "websocketpp exception: " << e.what(); + while (1) // temporary workaround for websocketpp throwing exceptions on access/close races + { // https://github.com/zaphoyd/websocketpp/issues/98 + try + { + mSEndpoint->get_io_service().run(); + break; + } + catch (websocketpp::exception& e) + { + Log(lsWARNING) << "websocketpp exception: " << e.what(); + } + } + } delete mSEndpoint; }else @@ -83,9 +102,28 @@ void WSDoor::startListening() // mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL); // Call the main-event-loop of the websocket server. - mEndpoint->listen( - boost::asio::ip::tcp::endpoint( - boost::asio::ip::address().from_string(mIp), mPort)); + try + { + mEndpoint->listen( + boost::asio::ip::tcp::endpoint( + boost::asio::ip::address().from_string(mIp), mPort)); + } + catch (websocketpp::exception& e) + { + Log(lsWARNING) << "websocketpp exception: " << e.what(); + while (1) // temporary workaround for websocketpp throwing exceptions on access/close races + { // https://github.com/zaphoyd/websocketpp/issues/98 + try + { + mEndpoint->get_io_service().run(); + break; + } + catch (websocketpp::exception& e) + { + Log(lsWARNING) << "websocketpp exception: " << e.what(); + } + } + } delete mEndpoint; }