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

This commit is contained in:
Arthur Britto
2012-12-10 14:42:37 -08:00
14 changed files with 424 additions and 90 deletions

View File

@@ -125,6 +125,7 @@
<ClCompile Include="src\cpp\ripple\LedgerMaster.cpp" /> <ClCompile Include="src\cpp\ripple\LedgerMaster.cpp" />
<ClCompile Include="src\cpp\ripple\LedgerProposal.cpp" /> <ClCompile Include="src\cpp\ripple\LedgerProposal.cpp" />
<ClCompile Include="src\cpp\ripple\LedgerTiming.cpp" /> <ClCompile Include="src\cpp\ripple\LedgerTiming.cpp" />
<ClCompile Include="src\cpp\ripple\LoadManager.cpp" />
<ClCompile Include="src\cpp\ripple\LoadMonitor.cpp" /> <ClCompile Include="src\cpp\ripple\LoadMonitor.cpp" />
<ClCompile Include="src\cpp\ripple\Log.cpp" /> <ClCompile Include="src\cpp\ripple\Log.cpp" />
<ClCompile Include="src\cpp\ripple\main.cpp" /> <ClCompile Include="src\cpp\ripple\main.cpp" />
@@ -183,7 +184,6 @@
<ClCompile Include="src\cpp\ripple\ValidationCollection.cpp" /> <ClCompile Include="src\cpp\ripple\ValidationCollection.cpp" />
<ClCompile Include="src\cpp\ripple\Wallet.cpp" /> <ClCompile Include="src\cpp\ripple\Wallet.cpp" />
<ClCompile Include="src\cpp\ripple\WalletAddTransactor.cpp" /> <ClCompile Include="src\cpp\ripple\WalletAddTransactor.cpp" />
<ClCompile Include="src\cpp\ripple\WSConnection.cpp" />
<ClCompile Include="src\cpp\ripple\WSDoor.cpp" /> <ClCompile Include="src\cpp\ripple\WSDoor.cpp" />
<ClCompile Include="src\cpp\ripple\WSHandler.cpp" /> <ClCompile Include="src\cpp\ripple\WSHandler.cpp" />
<ClCompile Include="src\cpp\websocketpp\src\base64\base64.cpp" /> <ClCompile Include="src\cpp\websocketpp\src\base64\base64.cpp" />

View File

@@ -276,9 +276,6 @@
<ClCompile Include="src\cpp\ripple\Wallet.cpp"> <ClCompile Include="src\cpp\ripple\Wallet.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\cpp\ripple\WSConnection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\WSDoor.cpp"> <ClCompile Include="src\cpp\ripple\WSDoor.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@@ -360,6 +357,9 @@
<ClCompile Include="src\cpp\ripple\WSHandler.cpp"> <ClCompile Include="src\cpp\ripple\WSHandler.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\cpp\ripple\LoadManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="util\pugiconfig.hpp"> <ClInclude Include="util\pugiconfig.hpp">

View File

@@ -3,6 +3,8 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "../database/database.h"
#include "LedgerMaster.h" #include "LedgerMaster.h"
#include "UniqueNodeList.h" #include "UniqueNodeList.h"
#include "ConnectionPool.h" #include "ConnectionPool.h"
@@ -17,9 +19,10 @@
#include "ValidationCollection.h" #include "ValidationCollection.h"
#include "Suppression.h" #include "Suppression.h"
#include "SNTPClient.h" #include "SNTPClient.h"
#include "../database/database.h"
#include "JobQueue.h" #include "JobQueue.h"
#include "RPCHandler.h" #include "RPCHandler.h"
#include "ProofOfWork.h"
#include "LoadManager.h"
class RPCDoor; class RPCDoor;
class PeerDoor; class PeerDoor;
@@ -58,6 +61,8 @@ class Application
SNTPClient mSNTPClient; SNTPClient mSNTPClient;
JobQueue mJobQueue; JobQueue mJobQueue;
RPCHandler mRPCHandler; RPCHandler mRPCHandler;
ProofOfWorkGenerator mPOWGen;
LoadManager mLoadMgr;
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB; DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
@@ -102,6 +107,8 @@ public:
SuppressionTable& getSuppression() { return mSuppressions; } SuppressionTable& getSuppression() { return mSuppressions; }
RPCHandler& getRPCHandler() { return mRPCHandler; } RPCHandler& getRPCHandler() { return mRPCHandler; }
boost::recursive_mutex& getMasterLock() { return mMasterLock; } boost::recursive_mutex& getMasterLock() { return mMasterLock; }
ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
LoadManager& getLoadManager() { return mLoadMgr; }
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); } bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }

View File

@@ -1,5 +1,22 @@
#include "LoadManager.h" #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 int LoadManager::getCreditRate() const
{ {
boost::mutex::scoped_lock sl(mLock); boost::mutex::scoped_lock sl(mLock);
@@ -84,6 +101,12 @@ bool LoadManager::shouldCutoff(LoadSource& source) const
return !source.isPrivileged() && (source.mBalance < mDebitLimit); return !source.isPrivileged() && (source.mBalance < mDebitLimit);
} }
bool LoadManager::adjust(LoadSource& source, LoadType t) const
{ // FIXME: Scale by category
LoadCost cost = mCosts[static_cast<int>(t)];
return adjust(source, cost.mCost);
}
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
time_t now = time(NULL); time_t now = time(NULL);

View File

@@ -1,10 +1,50 @@
#ifndef LOADSOURCE__H #ifndef LOADSOURCE__H
#define LOADSOURCE__H #define LOADSOURCE__H
#include <vector>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include "types.h" #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 class LoadSource
{ // a single endpoint that can impose load { // a single endpoint that can impose load
friend class LoadManager; friend class LoadManager;
@@ -40,17 +80,20 @@ protected:
int mCreditRate; // credits gained/lost per second int mCreditRate; // credits gained/lost per second
int mCreditLimit; // the most credits a source can have 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) int mDebitLimit; // when a source drops below this, we cut it off (should be negative)
mutable boost::mutex mLock; mutable boost::mutex mLock;
void canonicalize(LoadSource&, const time_t now) const; void canonicalize(LoadSource&, const time_t now) const;
std::vector<LoadCost> mCosts;
void addLoadCost(const LoadCost& c) { mCosts[static_cast<int>(c.mType)] = c; }
public: public:
LoadManager(int creditRate, int creditLimit, int debitWarn, int debitLimit) : LoadManager(int creditRate = 10, int creditLimit = 50, int debitWarn = -50, int debitLimit = -100);
mCreditRate(creditRate), mCreditLimit(creditLimit), mDebitWarn(debitWarn), mDebitLimit(debitLimit) { ; }
int getCreditRate() const; int getCreditRate() const;
int getCreditLimit() const; int getCreditLimit() const;
@@ -64,6 +107,9 @@ public:
bool shouldWarn(LoadSource&) const; bool shouldWarn(LoadSource&) const;
bool shouldCutoff(LoadSource&) const; bool shouldCutoff(LoadSource&) const;
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;
int getCost(LoadType t) { return mCosts[static_cast<int>(t)].mCost; }
}; };
class LoadFeeTrack class LoadFeeTrack

View File

@@ -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

View File

@@ -12,4 +12,5 @@ Offer::Offer(SerializedLedgerEntry::pointer ledgerEntry) : AccountItem(ledgerEnt
mAccount=mLedgerEntry->getFieldAccount(sfAccount); mAccount=mLedgerEntry->getFieldAccount(sfAccount);
mTakerGets = mLedgerEntry->getFieldAmount(sfTakerGets); mTakerGets = mLedgerEntry->getFieldAmount(sfTakerGets);
mTakerPays = mLedgerEntry->getFieldAmount(sfTakerPays); mTakerPays = mLedgerEntry->getFieldAmount(sfTakerPays);
mSeq = mLedgerEntry->getFieldU32(sfSequence);
} }

View File

@@ -6,6 +6,7 @@ class Offer : public AccountItem
RippleAddress mAccount; RippleAddress mAccount;
STAmount mTakerGets; STAmount mTakerGets;
STAmount mTakerPays; STAmount mTakerPays;
int mSeq;
Offer(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger Offer(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger
@@ -17,5 +18,6 @@ public:
STAmount getTakerPays(){ return(mTakerPays); } STAmount getTakerPays(){ return(mTakerPays); }
STAmount getTakerGets(){ return(mTakerGets); } STAmount getTakerGets(){ return(mTakerGets); }
RippleAddress getAccount(){ return(mAccount); } RippleAddress getAccount(){ return(mAccount); }
int getSeq(){ return(mSeq); }
}; };

View File

@@ -0,0 +1,159 @@
#include "ParameterTable.h"
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
#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<std::string, Parameter::pointer>::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<std::string, Parameter::pointer>::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<ParameterNode*>(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<std::string, Parameter::pointer>::iterator it = mChildren.find(name);
if (it != mChildren.end())
return false;
mChildren[name] = node;
return true;
}
std::map<std::string, Parameter::pointer>::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<ParameterNode>(getShared(), name.substr(0, dot));
n = dynamic_cast<ParameterNode*>(node.get());
assert(n);
mChildren[name] = node;
}
else
{ // existing node passed through must be inner
ParameterNode* n = dynamic_cast<ParameterNode*>(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<std::string, Parameter::ref> 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<std::string, Parameter::ref> 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<int>(value.asString());
}
catch (...)
{
}
}
error = Json::objectValue;
error["error"] = "Cannot convert to integer";
error["value"] = value;
return false;
}

View File

@@ -0,0 +1,72 @@
#ifndef PARAMETER_TABLE__H
#define PARAMETER_TABLE__H
#include <string>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "../json/value.h"
class Parameter : public boost::enable_shared_from_this<Parameter>
{ // abstract base class parameters are derived from
public:
typedef boost::shared_ptr<Parameter> pointer;
typedef const boost::shared_ptr<Parameter>& 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<std::string, Parameter::pointer> 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

View File

@@ -600,11 +600,11 @@ void Peer::processReadBuffer()
} }
} }
void Peer::punishPeer(const boost::weak_ptr<Peer>& wp, PeerPunish pp) void Peer::punishPeer(const boost::weak_ptr<Peer>& wp, LoadType l)
{ {
Peer::pointer p = wp.lock(); Peer::pointer p = wp.lock();
if (p) if (p)
p->punishPeer(pp); p->punishPeer(l);
} }
void Peer::recvHello(ripple::TMHello& packet) void Peer::recvHello(ripple::TMHello& packet)
@@ -743,7 +743,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx
if (tx->getStatus() == INVALID) if (tx->getStatus() == INVALID)
{ {
theApp->getSuppression().setFlag(stx->getTransactionID(), SF_BAD); theApp->getSuppression().setFlag(stx->getTransactionID(), SF_BAD);
Peer::punishPeer(peer, PP_BAD_SIGNATURE); Peer::punishPeer(peer, LT_InvalidSignature);
return; return;
} }
else else
@@ -759,7 +759,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx
catch (...) catch (...)
{ {
theApp->getSuppression().setFlags(stx->getTransactionID(), SF_BAD); theApp->getSuppression().setFlags(stx->getTransactionID(), SF_BAD);
punishPeer(peer, PP_INVALID_REQUEST); punishPeer(peer, LT_InvalidRequest);
} }
#endif #endif
} }
@@ -783,7 +783,7 @@ void Peer::recvTransaction(ripple::TMTransaction& packet)
{ // we have seen this transaction recently { // we have seen this transaction recently
if ((flags & SF_BAD) != 0) if ((flags & SF_BAD) != 0)
{ {
punishPeer(PP_BAD_SIGNATURE); punishPeer(LT_InvalidSignature);
return; return;
} }
@@ -828,7 +828,7 @@ static void checkPropose(Job& job, boost::shared_ptr<ripple::TMProposeSet> packe
if (!proposal->checkSign(set.signature())) if (!proposal->checkSign(set.signature()))
{ {
cLog(lsWARNING) << "proposal with previous ledger fails signature check"; cLog(lsWARNING) << "proposal with previous ledger fails signature check";
Peer::punishPeer(peer, PP_BAD_SIGNATURE); Peer::punishPeer(peer, LT_InvalidSignature);
return; return;
} }
else else
@@ -874,14 +874,14 @@ void Peer::recvPropose(const boost::shared_ptr<ripple::TMProposeSet>& packet)
(set.signature().size() < 56) || (set.nodepubkey().size() > 128) || (set.signature().size() > 128)) (set.signature().size() < 56) || (set.nodepubkey().size() > 128) || (set.signature().size() > 128))
{ {
cLog(lsWARNING) << "Received proposal is malformed"; cLog(lsWARNING) << "Received proposal is malformed";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidSignature);
return; return;
} }
if (set.has_previousledger() && (set.previousledger().size() != 32)) if (set.has_previousledger() && (set.previousledger().size() != 32))
{ {
cLog(lsWARNING) << "Received proposal is malformed"; cLog(lsWARNING) << "Received proposal is malformed";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
@@ -930,7 +930,7 @@ void Peer::recvHaveTxSet(ripple::TMHaveTransactionSet& packet)
uint256 hashes; uint256 hashes;
if (packet.hash().size() != (256 / 8)) if (packet.hash().size() != (256 / 8))
{ {
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
uint256 hash; uint256 hash;
@@ -938,7 +938,7 @@ void Peer::recvHaveTxSet(ripple::TMHaveTransactionSet& packet)
if (packet.status() == ripple::tsHAVE) if (packet.status() == ripple::tsHAVE)
addTxSet(hash); addTxSet(hash);
if (!theApp->getOPs().hasTXSet(shared_from_this(), hash, packet.status())) 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, 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)) if (!val->isValid(signingHash))
{ {
cLog(lsWARNING) << "Validation is invalid"; cLog(lsWARNING) << "Validation is invalid";
Peer::punishPeer(peer, PP_UNKNOWN_REQUEST); Peer::punishPeer(peer, LT_InvalidRequest);
return; return;
} }
@@ -966,7 +966,7 @@ static void checkValidation(Job&, SerializedValidation::pointer val, uint256 sig
catch (...) catch (...)
{ {
cLog(lsWARNING) << "Exception processing validation"; cLog(lsWARNING) << "Exception processing validation";
Peer::punishPeer(peer, PP_UNKNOWN_REQUEST); Peer::punishPeer(peer, LT_InvalidRequest);
} }
#endif #endif
} }
@@ -976,7 +976,7 @@ void Peer::recvValidation(const boost::shared_ptr<ripple::TMValidation>& packet)
if (packet->validation().size() < 50) if (packet->validation().size() < 50)
{ {
cLog(lsWARNING) << "Too small validation from peer"; cLog(lsWARNING) << "Too small validation from peer";
punishPeer(PP_UNKNOWN_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
@@ -1004,7 +1004,7 @@ void Peer::recvValidation(const boost::shared_ptr<ripple::TMValidation>& packet)
catch (...) catch (...)
{ {
cLog(lsWARNING) << "Exception processing validation"; cLog(lsWARNING) << "Exception processing validation";
punishPeer(PP_UNKNOWN_REQUEST); punishPeer(LT_InvalidRequest);
} }
#endif #endif
} }
@@ -1138,10 +1138,32 @@ void Peer::recvAccount(ripple::TMAccount& packet)
void Peer::recvProofWork(ripple::TMProofWork& 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()) if (packet.has_result())
{ // this is a reply to a proof of work we sent { // this is a reply to a proof of work we sent
// WRITEME // WRITEME
return;
} }
if (packet.has_target() && packet.has_challenge() && packet.has_iterations()) if (packet.has_target() && packet.has_challenge() && packet.has_iterations())
@@ -1151,7 +1173,7 @@ void Peer::recvProofWork(ripple::TMProofWork& packet)
uint256 challenge, target; uint256 challenge, target;
if ((packet.challenge().size() != (256 / 8)) || (packet.target().size() != (256 / 8))) if ((packet.challenge().size() != (256 / 8)) || (packet.target().size() != (256 / 8)))
{ {
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
memcpy(challenge.begin(), packet.challenge().data(), 256 / 8); memcpy(challenge.begin(), packet.challenge().data(), 256 / 8);
@@ -1160,7 +1182,7 @@ void Peer::recvProofWork(ripple::TMProofWork& packet)
challenge, target); challenge, target);
if (!pow->isValid()) if (!pow->isValid())
{ {
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
@@ -1232,7 +1254,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
cLog(lsINFO) << "Received request for TX candidate set data " << getIP(); cLog(lsINFO) << "Received request for TX candidate set data " << getIP();
if ((!packet.has_ledgerhash() || packet.ledgerhash().size() != 32)) if ((!packet.has_ledgerhash() || packet.ledgerhash().size() != 32))
{ {
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
cLog(lsWARNING) << "invalid request"; cLog(lsWARNING) << "invalid request";
return; return;
} }
@@ -1263,7 +1285,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
return; return;
} }
cLog(lsERROR) << "We do not have the map our peer wants"; cLog(lsERROR) << "We do not have the map our peer wants";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
reply.set_ledgerseq(0); reply.set_ledgerseq(0);
@@ -1281,7 +1303,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
uint256 ledgerhash; uint256 ledgerhash;
if (packet.ledgerhash().size() != 32) if (packet.ledgerhash().size() != 32)
{ {
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
cLog(lsWARNING) << "Invalid request"; cLog(lsWARNING) << "Invalid request";
return; return;
} }
@@ -1326,14 +1348,14 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
} }
else else
{ {
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
cLog(lsWARNING) << "Can't figure out what ledger they want"; cLog(lsWARNING) << "Can't figure out what ledger they want";
return; return;
} }
if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq() != ledger->getLedgerSeq()))) if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq() != ledger->getLedgerSeq())))
{ {
punishPeer(PP_UNKNOWN_REQUEST); punishPeer(LT_InvalidRequest);
if (sLog(lsWARNING)) if (sLog(lsWARNING))
{ {
if (ledger) if (ledger)
@@ -1391,7 +1413,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
if ((!map) || (packet.nodeids_size() == 0)) if ((!map) || (packet.nodeids_size() == 0))
{ {
cLog(lsWARNING) << "Can't find map or empty request"; cLog(lsWARNING) << "Can't find map or empty request";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
@@ -1401,7 +1423,7 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
if(!mn.isValid()) if(!mn.isValid())
{ {
cLog(lsWARNING) << "Request for invalid node"; cLog(lsWARNING) << "Request for invalid node";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
std::vector<SHAMapNode> nodeIDs; std::vector<SHAMapNode> nodeIDs;
@@ -1434,7 +1456,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet)
if (packet.nodes().size() <= 0) if (packet.nodes().size() <= 0)
{ {
cLog(lsWARNING) << "Ledger/TXset data with no nodes"; cLog(lsWARNING) << "Ledger/TXset data with no nodes";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
@@ -1449,7 +1471,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet)
else else
{ {
cLog(lsINFO) << "Unable to route TX/ledger data reply"; cLog(lsINFO) << "Unable to route TX/ledger data reply";
punishPeer(PP_UNWANTED_DATA); punishPeer(LT_UnwantedData);
} }
return; return;
} }
@@ -1460,7 +1482,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet)
if(packet.ledgerhash().size() != 32) if(packet.ledgerhash().size() != 32)
{ {
cLog(lsWARNING) << "TX candidate reply with invalid hash size"; cLog(lsWARNING) << "TX candidate reply with invalid hash size";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
memcpy(hash.begin(), packet.ledgerhash().data(), 32); 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)) if (!node.has_nodeid() || !node.has_nodedata() || (node.nodeid().size() != 33))
{ {
cLog(lsWARNING) << "LedgerData request with invalid node ID"; cLog(lsWARNING) << "LedgerData request with invalid node ID";
punishPeer(PP_INVALID_REQUEST); punishPeer(LT_InvalidRequest);
return; return;
} }
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size())); 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); SMAddNode san = theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData);
if (san.isInvalid()) if (san.isInvalid())
punishPeer(PP_UNWANTED_DATA); punishPeer(LT_UnwantedData);
return; return;
} }
SMAddNode san = theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()); SMAddNode san = theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this());
if (san.isInvalid()) if (san.isInvalid())
punishPeer(PP_UNWANTED_DATA); punishPeer(LT_UnwantedData);
} }
bool Peer::hasLedger(const uint256& hash) const bool Peer::hasLedger(const uint256& hash) const
@@ -1603,8 +1625,12 @@ void Peer::sendGetPeers()
sendPacket(packet); 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> peer, ProofOfWork::pointer pow) void Peer::doProofOfWork(Job&, boost::weak_ptr<Peer> peer, ProofOfWork::pointer pow)

View File

@@ -15,22 +15,7 @@
#include "InstanceCounter.h" #include "InstanceCounter.h"
#include "JobQueue.h" #include "JobQueue.h"
#include "ProofOfWork.h" #include "ProofOfWork.h"
#include "LoadManager.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
};
typedef std::pair<std::string,int> ipPort; typedef std::pair<std::string,int> ipPort;
@@ -57,6 +42,7 @@ private:
uint256 mCookieHash; uint256 mCookieHash;
uint64 mPeerId; uint64 mPeerId;
bool mPrivate; // Keep peer IP private. bool mPrivate; // Keep peer IP private.
LoadSource mLoad;
uint256 mClosedLedgerHash, mPreviousLedgerHash; uint256 mClosedLedgerHash, mPreviousLedgerHash;
std::list<uint256> mRecentLedgers; std::list<uint256> mRecentLedgers;
@@ -151,8 +137,8 @@ public:
void sendGetFullLedger(uint256& hash); void sendGetFullLedger(uint256& hash);
void sendGetPeers(); void sendGetPeers();
void punishPeer(PeerPunish pp); void punishPeer(LoadType);
static void punishPeer(const boost::weak_ptr<Peer>&, PeerPunish); static void punishPeer(const boost::weak_ptr<Peer>&, LoadType);
Json::Value getJson(); Json::Value getJson();
bool isConnected() const { return mHelloed && !mDetaching; } bool isConnected() const { return mHelloed && !mDetaching; }

View File

@@ -643,6 +643,7 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest)
//obj["account"] = account.humanAccountID(); //obj["account"] = account.humanAccountID();
obj["taker_pays"] = takerPays.getJson(0); obj["taker_pays"] = takerPays.getJson(0);
obj["taker_gets"] = takerGets.getJson(0); obj["taker_gets"] = takerGets.getJson(0);
obj["seq"] = offer->getSeq();
jsonLines.append(obj); jsonLines.append(obj);
} }

View File

@@ -66,9 +66,28 @@ void WSDoor::startListening()
// mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL); // mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL);
// Call the main-event-loop of the websocket server. // Call the main-event-loop of the websocket server.
mSEndpoint->listen( try
boost::asio::ip::tcp::endpoint( {
boost::asio::ip::address().from_string(mIp), mPort)); 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; delete mSEndpoint;
}else }else
@@ -83,9 +102,28 @@ void WSDoor::startListening()
// mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL); // mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL);
// Call the main-event-loop of the websocket server. // Call the main-event-loop of the websocket server.
mEndpoint->listen( try
boost::asio::ip::tcp::endpoint( {
boost::asio::ip::address().from_string(mIp), mPort)); 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; delete mEndpoint;
} }