Refactor ValidationCollection into IValidations

This commit is contained in:
Vinnie Falco
2013-06-01 09:52:48 -07:00
parent ec732ed113
commit 456b6e5460
12 changed files with 551 additions and 532 deletions

View File

@@ -33,100 +33,6 @@
#include "ripple_ledger.h"
#include "../ripple_data/ripple_data.h"
//#define WIN32_LEAN_AND_MEAN
#include <algorithm>
#include <cassert>
#include <fstream>
#include <iostream>
#include <openssl/ec.h>
#include <openssl/ripemd.h>
#include <openssl/sha.h>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/pointer_cast.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/unordered_set.hpp>
#include "src/cpp/database/SqliteDatabase.h"
#include "src/cpp/ripple/AcceptedLedger.h"
#include "src/cpp/ripple/AccountItems.h"
#include "src/cpp/ripple/AccountSetTransactor.h"
#include "src/cpp/ripple/AccountState.h"
#include "src/cpp/ripple/Application.h"
#include "src/cpp/ripple/CanonicalTXSet.h"
#include "src/cpp/ripple/ChangeTransactor.h"
#include "src/cpp/ripple/Config.h"
#include "src/cpp/ripple/HashPrefixes.h"
#include "src/cpp/ripple/Ledger.h"
#include "src/cpp/ripple/LedgerAcquire.h"
#include "src/cpp/ripple/LedgerConsensus.h"
#include "src/cpp/ripple/LedgerEntrySet.h"
#include "src/cpp/ripple/LedgerFormats.h"
#include "src/cpp/ripple/LedgerHistory.h"
#include "src/cpp/ripple/LedgerMaster.h"
#include "src/cpp/ripple/LedgerProposal.h"
#include "src/cpp/ripple/LedgerTiming.h"
#include "src/cpp/ripple/NetworkOPs.h"
#include "src/cpp/ripple/NicknameState.h"
#include "src/cpp/ripple/Offer.h"
#include "src/cpp/ripple/OfferCancelTransactor.h"
#include "src/cpp/ripple/OfferCreateTransactor.h"
#include "src/cpp/ripple/OrderBook.h"
#include "src/cpp/ripple/OrderBookDB.h"
#include "src/cpp/ripple/PackedMessage.h"
#include "src/cpp/ripple/PaymentTransactor.h"
#include "src/cpp/ripple/PFRequest.h"
#include "src/cpp/ripple/RegularKeySetTransactor.h"
#include "src/cpp/ripple/RippleCalc.h"
#include "src/cpp/ripple/RippleState.h"
#include "src/cpp/ripple/SerializedLedger.h"
#include "src/cpp/ripple/SerializedObject.h"
#include "src/cpp/ripple/SerializedTransaction.h"
#include "src/cpp/ripple/SerializedTypes.h"
#include "src/cpp/ripple/SerializedValidation.h"
#include "src/cpp/ripple/SHAMapSync.h"
#include "src/cpp/ripple/Transaction.h"
#include "src/cpp/ripple/TransactionEngine.h"
#include "src/cpp/ripple/TransactionErr.h"
#include "src/cpp/ripple/TransactionFormats.h"
#include "src/cpp/ripple/TransactionMaster.h"
#include "src/cpp/ripple/TransactionMeta.h"
#include "src/cpp/ripple/TransactionQueue.h"
#include "src/cpp/ripple/Transactor.h"
#include "src/cpp/ripple/TrustSetTransactor.h"
#include "src/cpp/ripple/ValidationCollection.h"
#include "src/cpp/ripple/Wallet.h"
#include "src/cpp/ripple/WalletAddTransactor.h"
// contract stuff, order matters
#include "src/cpp/ripple/ScriptData.h"
#include "src/cpp/ripple/Contract.h"
#include "src/cpp/ripple/Interpreter.h"
#include "src/cpp/ripple/Operation.h"
// New abstract interfaces
#include "src/cpp/ripple/ripple_IFeatures.h"
#include "src/cpp/ripple/ripple_IFeeVote.h"
#include "src/cpp/ripple/ripple_ILoadFeeTrack.h"
#include "src/cpp/ripple/FeatureTable.h"
//------------------------------------------------------------------------------
// main
@@ -196,6 +102,7 @@
#include "src/cpp/ripple/ripple_FeeVote.cpp"
#include "src/cpp/ripple/ripple_LoadFeeTrack.cpp"
#include "src/cpp/ripple/ripple_Validations.cpp"
#ifdef _MSC_VER
//#pragma warning (pop)

View File

@@ -34,4 +34,98 @@
#include "modules/ripple_basics/ripple_basics.h"
#include "../ripple_data/ripple_data.h"
//#define WIN32_LEAN_AND_MEAN
#include <algorithm>
#include <cassert>
#include <fstream>
#include <iostream>
#include <openssl/ec.h>
#include <openssl/ripemd.h>
#include <openssl/sha.h>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/pointer_cast.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/unordered_set.hpp>
#include "src/cpp/database/SqliteDatabase.h"
#include "src/cpp/ripple/AcceptedLedger.h"
#include "src/cpp/ripple/AccountItems.h"
#include "src/cpp/ripple/AccountSetTransactor.h"
#include "src/cpp/ripple/AccountState.h"
#include "src/cpp/ripple/Application.h"
#include "src/cpp/ripple/CanonicalTXSet.h"
#include "src/cpp/ripple/ChangeTransactor.h"
#include "src/cpp/ripple/Config.h"
#include "src/cpp/ripple/HashPrefixes.h"
#include "src/cpp/ripple/Ledger.h"
#include "src/cpp/ripple/LedgerAcquire.h"
#include "src/cpp/ripple/LedgerConsensus.h"
#include "src/cpp/ripple/LedgerEntrySet.h"
#include "src/cpp/ripple/LedgerFormats.h"
#include "src/cpp/ripple/LedgerHistory.h"
#include "src/cpp/ripple/LedgerMaster.h"
#include "src/cpp/ripple/LedgerProposal.h"
#include "src/cpp/ripple/LedgerTiming.h"
#include "src/cpp/ripple/NetworkOPs.h"
#include "src/cpp/ripple/NicknameState.h"
#include "src/cpp/ripple/Offer.h"
#include "src/cpp/ripple/OfferCancelTransactor.h"
#include "src/cpp/ripple/OfferCreateTransactor.h"
#include "src/cpp/ripple/OrderBook.h"
#include "src/cpp/ripple/OrderBookDB.h"
#include "src/cpp/ripple/PackedMessage.h"
#include "src/cpp/ripple/PaymentTransactor.h"
#include "src/cpp/ripple/PFRequest.h"
#include "src/cpp/ripple/RegularKeySetTransactor.h"
#include "src/cpp/ripple/RippleCalc.h"
#include "src/cpp/ripple/RippleState.h"
#include "src/cpp/ripple/SerializedLedger.h"
#include "src/cpp/ripple/SerializedObject.h"
#include "src/cpp/ripple/SerializedTransaction.h"
#include "src/cpp/ripple/SerializedTypes.h"
#include "src/cpp/ripple/SerializedValidation.h"
#include "src/cpp/ripple/SHAMapSync.h"
#include "src/cpp/ripple/Transaction.h"
#include "src/cpp/ripple/TransactionEngine.h"
#include "src/cpp/ripple/TransactionErr.h"
#include "src/cpp/ripple/TransactionFormats.h"
#include "src/cpp/ripple/TransactionMaster.h"
#include "src/cpp/ripple/TransactionMeta.h"
#include "src/cpp/ripple/TransactionQueue.h"
#include "src/cpp/ripple/Transactor.h"
#include "src/cpp/ripple/TrustSetTransactor.h"
#include "src/cpp/ripple/Wallet.h"
#include "src/cpp/ripple/WalletAddTransactor.h"
// contract stuff, order matters
#include "src/cpp/ripple/ScriptData.h"
#include "src/cpp/ripple/Contract.h"
#include "src/cpp/ripple/Interpreter.h"
#include "src/cpp/ripple/Operation.h"
// New abstract interfaces
#include "src/cpp/ripple/ripple_IFeatures.h"
#include "src/cpp/ripple/ripple_IFeeVote.h"
#include "src/cpp/ripple/ripple_ILoadFeeTrack.h"
#include "src/cpp/ripple/ripple_IValidations.h"
#include "src/cpp/ripple/FeatureTable.h"
#endif

View File

@@ -41,7 +41,6 @@
#include "src/cpp/ripple/LoadMonitor.cpp"
#include "src/cpp/ripple/UpdateTables.cpp"
#include "src/cpp/ripple/main.cpp"
#include "src/cpp/ripple/ValidationCollection.cpp"
#include "misc/ripple_HashValue.cpp"

View File

@@ -24,11 +24,10 @@
#include "ripple_net.h"
#include "../ripple_data/ripple_data.h"
#include "../websocketpp/src/logger/logger.hpp" // for ripple_LogWebSockets.cpp
#include "src/cpp/ripple/ripple_ILoadFeeTrack.h" // for NetworkOPs
#include "../ripple_data/ripple_data.h"
#include "../ripple_ledger/ripple_ledger.h"
// VFALCO: TODO, fix these warnings!
#ifdef _MSC_VER

View File

@@ -992,6 +992,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_Validations.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\rpc.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1178,12 +1184,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ValidationCollection.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\Wallet.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1656,6 +1656,7 @@
<ClInclude Include="src\cpp\ripple\ripple_IFeatures.h" />
<ClInclude Include="src\cpp\ripple\ripple_IFeeVote.h" />
<ClInclude Include="src\cpp\ripple\ripple_ILoadFeeTrack.h" />
<ClInclude Include="src\cpp\ripple\ripple_IValidations.h" />
<ClInclude Include="src\cpp\ripple\RPC.h" />
<ClInclude Include="src\cpp\ripple\RPCDoor.h" />
<ClInclude Include="src\cpp\ripple\RPCErr.h" />
@@ -1682,7 +1683,6 @@
<ClInclude Include="src\cpp\ripple\Transactor.h" />
<ClInclude Include="src\cpp\ripple\TrustSetTransactor.h" />
<ClInclude Include="src\cpp\ripple\UniqueNodeList.h" />
<ClInclude Include="src\cpp\ripple\ValidationCollection.h" />
<ClInclude Include="src\cpp\ripple\Version.h" />
<ClInclude Include="src\cpp\ripple\Wallet.h" />
<ClInclude Include="src\cpp\ripple\WalletAddTransactor.h" />

View File

@@ -618,9 +618,6 @@
<ClCompile Include="src\cpp\ripple\main.cpp">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ValidationCollection.cpp">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClCompile>
<ClCompile Include="modules\ripple_main\ripple_main.cpp">
<Filter>1. Modules\ripple_main</Filter>
</ClCompile>
@@ -798,6 +795,9 @@
<ClCompile Include="src\cpp\ripple\ripple_DatabaseCon.cpp">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_Validations.cpp">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="database\sqlite3ext.h">
@@ -1262,9 +1262,6 @@
<ClInclude Include="src\cpp\ripple\LoadMonitor.h">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\ValidationCollection.h">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClInclude>
<ClInclude Include="modules\ripple_main\ripple_main.h">
<Filter>1. Modules\ripple_main</Filter>
</ClInclude>
@@ -1484,6 +1481,9 @@
<ClInclude Include="src\cpp\ripple\ripple_DatabaseCon.h">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\ripple_IValidations.h">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="SConstruct" />

View File

@@ -36,6 +36,7 @@ Application::Application()
, mJobQueue (mIOService)
, mFeeVote (IFeeVote::New (10, 50 * SYSTEM_CURRENCY_PARTS, 12.5 * SYSTEM_CURRENCY_PARTS))
, mFeeTrack (ILoadFeeTrack::New ())
, mValidations (IValidations::New ())
, mFeatureTable (2 * 7 * 24 * 60 * 60, 200) // two weeks, 200/256
// VFALCO: TODO replace all NULL with nullptr
, mRpcDB (NULL)
@@ -74,7 +75,7 @@ void Application::stop()
mShutdown = true;
mIOService.stop();
mHashedObjectStore.waitWrite();
mValidations.flush();
mValidations->flush();
mAuxService.stop();
mJobQueue.shutdown();
@@ -246,7 +247,7 @@ void Application::setup()
if (!theConfig.RUN_STANDALONE)
getUNL().nodeBootstrap();
mValidations.tune(theConfig.getSize(siValidationsSize), theConfig.getSize(siValidationsAge));
mValidations->tune(theConfig.getSize(siValidationsSize), theConfig.getSize(siValidationsAge));
mHashedObjectStore.tune(theConfig.getSize(siNodeCacheSize), theConfig.getSize(siNodeCacheAge));
mLedgerMaster.tune(theConfig.getSize(siLedgerSize), theConfig.getSize(siLedgerAge));
mSLECache.setTargetSize(theConfig.getSize(siSLECacheSize));
@@ -401,7 +402,7 @@ void Application::sweep()
mHashedObjectStore.sweep();
mLedgerMaster.sweep();
mTempNodeCache.sweep();
mValidations.sweep();
mValidations->sweep();
getMasterLedgerAcquire().sweep();
mSLECache.sweep();
AcceptedLedger::sweep();
@@ -413,8 +414,10 @@ void Application::sweep()
Application::~Application()
{
delete mValidations;
delete mFeeTrack;
delete mFeeVote;
delete mTxnDB;
delete mLedgerDB;
delete mWalletDB;

View File

@@ -17,7 +17,6 @@
#include "Peer.h"
#include "NetworkOPs.h"
#include "WSDoor.h"
#include "ValidationCollection.h"
#include "Suppression.h"
#include "SNTPClient.h"
#include "JobQueue.h"
@@ -33,6 +32,7 @@
class IFeatureTable;
class IFeeVote;
class ILoadFeeTrack;
class IValidations;
class RPCDoor;
class PeerDoor;
@@ -53,7 +53,6 @@ class Application
TransactionMaster mMasterTransaction;
NetworkOPs mNetOps;
NodeCache mTempNodeCache;
ValidationCollection mValidations;
SuppressionTable mSuppressions;
HashedObjectStore mHashedObjectStore;
SLECache mSLECache;
@@ -63,8 +62,13 @@ class Application
LoadManager mLoadMgr;
TXQueue mTxnQueue;
OrderBookDB mOrderBookDB;
// VFALCO: Clean stuff
IFeeVote* mFeeVote;
ILoadFeeTrack* mFeeTrack;
IValidations* mValidations;
// VFALCO: End Clean stuff
FeatureTable mFeatureTable;
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mNetNodeDB, *mPathFindDB, *mHashNodeDB;
@@ -111,20 +115,20 @@ public:
TransactionMaster& getMasterTransaction() { return mMasterTransaction; }
NodeCache& getTempNodeCache() { return mTempNodeCache; }
HashedObjectStore& getHashedObjectStore() { return mHashedObjectStore; }
ValidationCollection& getValidations() { return mValidations; }
JobQueue& getJobQueue() { return mJobQueue; }
SuppressionTable& getSuppression() { return mSuppressions; }
boost::recursive_mutex& getMasterLock() { return mMasterLock; }
ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
LoadManager& getLoadManager() { return mLoadMgr; }
ILoadFeeTrack& getFeeTrack() { return *mFeeTrack; }
TXQueue& getTxnQueue() { return mTxnQueue; }
PeerDoor& getPeerDoor() { return *mPeerDoor; }
OrderBookDB& getOrderBookDB() { return mOrderBookDB; }
SLECache& getSLECache() { return mSLECache; }
IFeeVote& getFeeVote() { return *mFeeVote; }
FeatureTable& getFeatureTable() { return mFeatureTable; }
IFeeVote& getFeeVote() { return *mFeeVote; }
ILoadFeeTrack& getFeeTrack() { return *mFeeTrack; }
IValidations& getValidations() { return *mValidations; }
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
bool isNew(const uint256& s, uint64 p) { return mSuppressions.addSuppressionPeer(s, p); }

View File

@@ -1,353 +0,0 @@
#include "ValidationCollection.h"
#include <boost/foreach.hpp>
#include "Application.h"
#include "LedgerTiming.h"
SETUP_LOG (ValidationCollection)
typedef std::map<uint160, SerializedValidation::pointer>::value_type u160_val_pair;
typedef boost::shared_ptr<ValidationSet> VSpointer;
void ValidationCollection::tune(int size, int age)
{
mValidations.setTargetSize(size);
mValidations.setTargetAge(age);
}
VSpointer ValidationCollection::findCreateSet(const uint256& ledgerHash)
{
VSpointer j = mValidations.fetch(ledgerHash);
if (!j)
{
j = boost::make_shared<ValidationSet>();
mValidations.canonicalize(ledgerHash, j);
}
return j;
}
VSpointer ValidationCollection::findSet(const uint256& ledgerHash)
{
return mValidations.fetch(ledgerHash);
}
bool ValidationCollection::addValidation(SerializedValidation::ref val, const std::string& source)
{
RippleAddress signer = val->getSignerPublic();
bool isCurrent = false;
if (theApp->getUNL().nodeInUNL(signer) || val->isTrusted())
{
val->setTrusted();
uint32 now = theApp->getOPs().getCloseTimeNC();
uint32 valClose = val->getSignTime();
if ((now > (valClose - LEDGER_EARLY_INTERVAL)) && (now < (valClose + LEDGER_VAL_INTERVAL)))
isCurrent = true;
else
{
WriteLog (lsWARNING, ValidationCollection) << "Received stale validation now=" << now << ", close=" << valClose;
}
}
else
{
WriteLog (lsDEBUG, ValidationCollection) << "Node " << signer.humanNodePublic() << " not in UNL st=" << val->getSignTime() <<
", hash=" << val->getLedgerHash() << ", shash=" << val->getSigningHash() << " src=" << source;
}
uint256 hash = val->getLedgerHash();
uint160 node = signer.getNodeID();
{
boost::mutex::scoped_lock sl(mValidationLock);
if (!findCreateSet(hash)->insert(std::make_pair(node, val)).second)
return false;
if (isCurrent)
{
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.find(node);
if (it == mCurrentValidations.end())
mCurrentValidations.emplace(node, val);
else if (!it->second)
it->second = val;
else if (val->getSignTime() > it->second->getSignTime())
{
val->setPreviousHash(it->second->getLedgerHash());
mStaleValidations.push_back(it->second);
it->second = val;
condWrite();
}
else
isCurrent = false;
}
}
WriteLog (lsDEBUG, ValidationCollection) << "Val for " << hash << " from " << signer.humanNodePublic()
<< " added " << (val->isTrusted() ? "trusted/" : "UNtrusted/") << (isCurrent ? "current" : "stale");
if (val->isTrusted())
theApp->getLedgerMaster().checkAccept(hash);
// FIXME: This never forwards untrusted validations
return isCurrent;
}
ValidationSet ValidationCollection::getValidations(const uint256& ledger)
{
{
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
return *set;
}
return ValidationSet();
}
void ValidationCollection::getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int &untrusted)
{
trusted = untrusted = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
uint32 now = theApp->getOPs().getNetworkTimeNC();
BOOST_FOREACH(u160_val_pair& it, *set)
{
bool isTrusted = it.second->isTrusted();
if (isTrusted && currentOnly)
{
uint32 closeTime = it.second->getSignTime();
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
isTrusted = false;
else
{
WriteLog (lsTRACE, ValidationCollection) << "VC: Untrusted due to time " << ledger;
}
}
if (isTrusted)
++trusted;
else
++untrusted;
}
}
WriteLog (lsTRACE, ValidationCollection) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
}
void ValidationCollection::getValidationTypes(const uint256& ledger, int& full, int& partial)
{
full = partial = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
BOOST_FOREACH(u160_val_pair& it, *set)
{
if (it.second->isTrusted())
{
if (it.second->isFull())
++full;
else
++partial;
}
}
}
WriteLog (lsTRACE, ValidationCollection) << "VC: " << ledger << "f:" << full << " p:" << partial;
}
int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
{
int trusted = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
BOOST_FOREACH(u160_val_pair& it, *set)
{
if (it.second->isTrusted())
++trusted;
}
}
return trusted;
}
int ValidationCollection::getNodesAfter(const uint256& ledger)
{ // Number of trusted nodes that have moved past this ledger
int count = 0;
boost::mutex::scoped_lock sl(mValidationLock);
BOOST_FOREACH(u160_val_pair& it, mCurrentValidations)
{
if (it.second->isTrusted() && it.second->isPreviousHash(ledger))
++count;
}
return count;
}
int ValidationCollection::getLoadRatio(bool overLoaded)
{ // how many trusted nodes are able to keep up, higher is better
int goodNodes = overLoaded ? 1 : 0;
int badNodes = overLoaded ? 0 : 1;
{
boost::mutex::scoped_lock sl(mValidationLock);
BOOST_FOREACH(u160_val_pair& it, mCurrentValidations)
{
if (it.second->isTrusted())
{
if (it.second->isFull())
++goodNodes;
else
++badNodes;
}
}
}
return (goodNodes * 100) / (goodNodes + badNodes);
}
std::list<SerializedValidation::pointer> ValidationCollection::getCurrentTrustedValidations()
{
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;
std::list<SerializedValidation::pointer> ret;
boost::mutex::scoped_lock sl(mValidationLock);
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
while (it != mCurrentValidations.end())
{
if (!it->second) // contains no record
it = mCurrentValidations.erase(it);
else if (it->second->getSignTime() < cutoff)
{ // contains a stale record
mStaleValidations.push_back(it->second);
it->second.reset();
condWrite();
it = mCurrentValidations.erase(it);
}
else
{ // contains a live record
if (it->second->isTrusted())
ret.push_back(it->second);
++it;
}
}
return ret;
}
boost::unordered_map<uint256, currentValidationCount>
ValidationCollection::getCurrentValidations(uint256 currentLedger, uint256 priorLedger)
{
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;
bool valCurrentLedger = currentLedger.isNonZero();
bool valPriorLedger = priorLedger.isNonZero();
boost::unordered_map<uint256, currentValidationCount> ret;
boost::mutex::scoped_lock sl(mValidationLock);
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
while (it != mCurrentValidations.end())
{
if (!it->second) // contains no record
it = mCurrentValidations.erase(it);
else if (it->second->getSignTime() < cutoff)
{ // contains a stale record
mStaleValidations.push_back(it->second);
it->second.reset();
condWrite();
it = mCurrentValidations.erase(it);
}
else
{ // contains a live record
bool countPreferred = valCurrentLedger && (it->second->getLedgerHash() == currentLedger);
if (!countPreferred && // allow up to one ledger slip in either direction
((valCurrentLedger && it->second->isPreviousHash(currentLedger)) ||
(valPriorLedger && (it->second->getLedgerHash() == priorLedger))))
{
countPreferred = true;
WriteLog (lsDEBUG, ValidationCollection) << "Counting for " << currentLedger << " not " << it->second->getLedgerHash();
}
currentValidationCount& p = countPreferred ? ret[currentLedger] : ret[it->second->getLedgerHash()];
++(p.first);
uint160 ni = it->second->getNodeID();
if (ni > p.second)
p.second = ni;
++it;
}
}
return ret;
}
void ValidationCollection::flush()
{
bool anyNew = false;
WriteLog (lsINFO, ValidationCollection) << "Flushing validations";
boost::mutex::scoped_lock sl(mValidationLock);
BOOST_FOREACH(u160_val_pair& it, mCurrentValidations)
{
if (it.second)
mStaleValidations.push_back(it.second);
anyNew = true;
}
mCurrentValidations.clear();
if (anyNew)
condWrite();
while (mWriting)
{
sl.unlock();
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
sl.lock();
}
WriteLog (lsDEBUG, ValidationCollection) << "Validations flushed";
}
void ValidationCollection::condWrite()
{
if (mWriting)
return;
mWriting = true;
theApp->getJobQueue().addJob(jtWRITE, "ValidationCollection::doWrite",
BIND_TYPE(&ValidationCollection::doWrite, this, P_1));
}
void ValidationCollection::doWrite(Job&)
{
LoadEvent::autoptr event(theApp->getJobQueue().getLoadEventAP(jtDISK, "ValidationWrite"));
boost::format insVal("INSERT INTO Validations "
"(LedgerHash,NodePubKey,SignTime,RawData) VALUES ('%s','%s','%u',%s);");
boost::mutex::scoped_lock sl(mValidationLock);
assert(mWriting);
while (!mStaleValidations.empty())
{
std::vector<SerializedValidation::pointer> vector;
vector.reserve(512);
mStaleValidations.swap(vector);
sl.unlock();
{
Database *db = theApp->getLedgerDB()->getDB();
ScopedLock dbl(theApp->getLedgerDB()->getDBLock());
Serializer s(1024);
db->executeSQL("BEGIN TRANSACTION;");
BOOST_FOREACH(SerializedValidation::ref it, vector)
{
s.erase();
it->add(s);
db->executeSQL(boost::str(insVal % it->getLedgerHash().GetHex()
% it->getSignerPublic().humanNodePublic() % it->getSignTime()
% sqlEscape(s.peekData())));
}
db->executeSQL("END TRANSACTION;");
}
sl.lock();
}
mWriting = false;
}
void ValidationCollection::sweep()
{
boost::mutex::scoped_lock sl(mValidationLock);
mValidations.sweep();
}
// vim:ts=4

View File

@@ -1,58 +0,0 @@
#ifndef __VALIDATION_COLLECTION__
#define __VALIDATION_COLLECTION__
#include <vector>
#include <boost/unordered_map.hpp>
#include <boost/thread/mutex.hpp>
#include "SerializedValidation.h"
#include "JobQueue.h"
typedef boost::unordered_map<uint160, SerializedValidation::pointer> ValidationSet;
typedef std::pair<int, uint160> currentValidationCount; // nodes validating and highest node ID validating
// VFALCO: TODO, Rename this to "Validations"
class ValidationCollection
{
protected:
boost::mutex mValidationLock;
TaggedCache<uint256, ValidationSet, UptimeTimerAdapter> mValidations;
boost::unordered_map<uint160, SerializedValidation::pointer> mCurrentValidations;
std::vector<SerializedValidation::pointer> mStaleValidations;
bool mWriting;
void doWrite(Job&);
void condWrite();
boost::shared_ptr<ValidationSet> findCreateSet(const uint256& ledgerHash);
boost::shared_ptr<ValidationSet> findSet(const uint256& ledgerHash);
public:
ValidationCollection() : mValidations("Validations", 128, 600), mWriting(false)
{ mStaleValidations.reserve(512); }
bool addValidation(SerializedValidation::ref, const std::string& source);
ValidationSet getValidations(const uint256& ledger);
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
void getValidationTypes(const uint256& ledger, int& full, int& partial);
int getTrustedValidationCount(const uint256& ledger);
int getNodesAfter(const uint256& ledger);
int getLoadRatio(bool overLoaded);
boost::unordered_map<uint256, currentValidationCount> getCurrentValidations(
uint256 currentLedger, uint256 previousLedger);
std::list<SerializedValidation::pointer> getCurrentTrustedValidations();
void tune(int size, int age);
void flush();
void sweep();
};
#endif

View File

@@ -0,0 +1,47 @@
#ifndef RIPPLE_IVALIDATIONS_H
#define RIPPLE_IVALIDATIONS_H
//#include <vector>
//#include <boost/unordered_map.hpp>
//#include <boost/thread/mutex.hpp>
//#include "SerializedValidation.h"
//#include "JobQueue.h"
// VFALCO: TODO rename and move these typedefs into the IValidations interface
typedef boost::unordered_map<uint160, SerializedValidation::pointer> ValidationSet;
typedef std::pair<int, uint160> currentValidationCount; // nodes validating and highest node ID validating
class IValidations
{
public:
static IValidations* New ();
virtual ~IValidations () { }
virtual bool addValidation (SerializedValidation::ref, const std::string& source) = 0;
virtual ValidationSet getValidations (const uint256& ledger) = 0;
virtual void getValidationCount (const uint256& ledger, bool currentOnly, int& trusted, int& untrusted) = 0;
virtual void getValidationTypes (const uint256& ledger, int& full, int& partial) = 0;
virtual int getTrustedValidationCount (const uint256& ledger) = 0;
virtual int getNodesAfter (const uint256& ledger) = 0;
virtual int getLoadRatio (bool overLoaded) = 0;
// VFALCO: TODO, make a typedef for this ugly return value!
virtual boost::unordered_map<uint256, currentValidationCount> getCurrentValidations (
uint256 currentLedger, uint256 previousLedger) = 0;
virtual std::list <SerializedValidation::pointer> getCurrentTrustedValidations () = 0;
virtual void tune (int size, int age) = 0;
virtual void flush () = 0;
virtual void sweep() = 0;
};
#endif

View File

@@ -0,0 +1,377 @@
#include <boost/foreach.hpp>
#include "Application.h"
#include "LedgerTiming.h"
class Validations;
SETUP_LOG (Validations)
typedef std::map<uint160, SerializedValidation::pointer>::value_type u160_val_pair;
typedef boost::shared_ptr<ValidationSet> VSpointer;
class Validations : public IValidations
{
private:
boost::mutex mValidationLock;
TaggedCache<uint256, ValidationSet, UptimeTimerAdapter> mValidations;
boost::unordered_map<uint160, SerializedValidation::pointer> mCurrentValidations;
std::vector<SerializedValidation::pointer> mStaleValidations;
bool mWriting;
private:
boost::shared_ptr<ValidationSet> findCreateSet(const uint256& ledgerHash)
{
VSpointer j = mValidations.fetch(ledgerHash);
if (!j)
{
j = boost::make_shared<ValidationSet>();
mValidations.canonicalize(ledgerHash, j);
}
return j;
}
boost::shared_ptr<ValidationSet> findSet(const uint256& ledgerHash)
{
return mValidations.fetch(ledgerHash);
}
public:
Validations() : mValidations("Validations", 128, 600), mWriting(false)
{
mStaleValidations.reserve(512);
}
private:
bool addValidation (SerializedValidation::ref val, const std::string& source)
{
RippleAddress signer = val->getSignerPublic();
bool isCurrent = false;
if (theApp->getUNL().nodeInUNL(signer) || val->isTrusted())
{
val->setTrusted();
uint32 now = theApp->getOPs().getCloseTimeNC();
uint32 valClose = val->getSignTime();
if ((now > (valClose - LEDGER_EARLY_INTERVAL)) && (now < (valClose + LEDGER_VAL_INTERVAL)))
isCurrent = true;
else
{
WriteLog (lsWARNING, Validations) << "Received stale validation now=" << now << ", close=" << valClose;
}
}
else
{
WriteLog (lsDEBUG, Validations) << "Node " << signer.humanNodePublic() << " not in UNL st=" << val->getSignTime() <<
", hash=" << val->getLedgerHash() << ", shash=" << val->getSigningHash() << " src=" << source;
}
uint256 hash = val->getLedgerHash();
uint160 node = signer.getNodeID();
{
boost::mutex::scoped_lock sl(mValidationLock);
if (!findCreateSet(hash)->insert(std::make_pair(node, val)).second)
return false;
if (isCurrent)
{
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.find(node);
if (it == mCurrentValidations.end())
mCurrentValidations.emplace(node, val);
else if (!it->second)
it->second = val;
else if (val->getSignTime() > it->second->getSignTime())
{
val->setPreviousHash(it->second->getLedgerHash());
mStaleValidations.push_back(it->second);
it->second = val;
condWrite();
}
else
isCurrent = false;
}
}
WriteLog (lsDEBUG, Validations) << "Val for " << hash << " from " << signer.humanNodePublic()
<< " added " << (val->isTrusted() ? "trusted/" : "UNtrusted/") << (isCurrent ? "current" : "stale");
if (val->isTrusted())
theApp->getLedgerMaster().checkAccept(hash);
// FIXME: This never forwards untrusted validations
return isCurrent;
}
void tune (int size, int age)
{
mValidations.setTargetSize(size);
mValidations.setTargetAge(age);
}
ValidationSet getValidations(const uint256& ledger)
{
{
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
return *set;
}
return ValidationSet();
}
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int &untrusted)
{
trusted = untrusted = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
uint32 now = theApp->getOPs().getNetworkTimeNC();
BOOST_FOREACH(u160_val_pair& it, *set)
{
bool isTrusted = it.second->isTrusted();
if (isTrusted && currentOnly)
{
uint32 closeTime = it.second->getSignTime();
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
isTrusted = false;
else
{
WriteLog (lsTRACE, Validations) << "VC: Untrusted due to time " << ledger;
}
}
if (isTrusted)
++trusted;
else
++untrusted;
}
}
WriteLog (lsTRACE, Validations) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
}
void getValidationTypes(const uint256& ledger, int& full, int& partial)
{
full = partial = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
BOOST_FOREACH(u160_val_pair& it, *set)
{
if (it.second->isTrusted())
{
if (it.second->isFull())
++full;
else
++partial;
}
}
}
WriteLog (lsTRACE, Validations) << "VC: " << ledger << "f:" << full << " p:" << partial;
}
int getTrustedValidationCount(const uint256& ledger)
{
int trusted = 0;
boost::mutex::scoped_lock sl(mValidationLock);
VSpointer set = findSet(ledger);
if (set)
{
BOOST_FOREACH(u160_val_pair& it, *set)
{
if (it.second->isTrusted())
++trusted;
}
}
return trusted;
}
int getNodesAfter(const uint256& ledger)
{ // Number of trusted nodes that have moved past this ledger
int count = 0;
boost::mutex::scoped_lock sl(mValidationLock);
BOOST_FOREACH(u160_val_pair& it, mCurrentValidations)
{
if (it.second->isTrusted() && it.second->isPreviousHash(ledger))
++count;
}
return count;
}
int getLoadRatio(bool overLoaded)
{ // how many trusted nodes are able to keep up, higher is better
int goodNodes = overLoaded ? 1 : 0;
int badNodes = overLoaded ? 0 : 1;
{
boost::mutex::scoped_lock sl(mValidationLock);
BOOST_FOREACH(u160_val_pair& it, mCurrentValidations)
{
if (it.second->isTrusted())
{
if (it.second->isFull())
++goodNodes;
else
++badNodes;
}
}
}
return (goodNodes * 100) / (goodNodes + badNodes);
}
std::list<SerializedValidation::pointer> getCurrentTrustedValidations()
{
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;
std::list<SerializedValidation::pointer> ret;
boost::mutex::scoped_lock sl(mValidationLock);
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
while (it != mCurrentValidations.end())
{
if (!it->second) // contains no record
it = mCurrentValidations.erase(it);
else if (it->second->getSignTime() < cutoff)
{ // contains a stale record
mStaleValidations.push_back(it->second);
it->second.reset();
condWrite();
it = mCurrentValidations.erase(it);
}
else
{ // contains a live record
if (it->second->isTrusted())
ret.push_back(it->second);
++it;
}
}
return ret;
}
boost::unordered_map<uint256, currentValidationCount>
getCurrentValidations(uint256 currentLedger, uint256 priorLedger)
{
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;
bool valCurrentLedger = currentLedger.isNonZero();
bool valPriorLedger = priorLedger.isNonZero();
boost::unordered_map<uint256, currentValidationCount> ret;
boost::mutex::scoped_lock sl(mValidationLock);
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
while (it != mCurrentValidations.end())
{
if (!it->second) // contains no record
it = mCurrentValidations.erase(it);
else if (it->second->getSignTime() < cutoff)
{ // contains a stale record
mStaleValidations.push_back(it->second);
it->second.reset();
condWrite();
it = mCurrentValidations.erase(it);
}
else
{ // contains a live record
bool countPreferred = valCurrentLedger && (it->second->getLedgerHash() == currentLedger);
if (!countPreferred && // allow up to one ledger slip in either direction
((valCurrentLedger && it->second->isPreviousHash(currentLedger)) ||
(valPriorLedger && (it->second->getLedgerHash() == priorLedger))))
{
countPreferred = true;
WriteLog (lsDEBUG, Validations) << "Counting for " << currentLedger << " not " << it->second->getLedgerHash();
}
currentValidationCount& p = countPreferred ? ret[currentLedger] : ret[it->second->getLedgerHash()];
++(p.first);
uint160 ni = it->second->getNodeID();
if (ni > p.second)
p.second = ni;
++it;
}
}
return ret;
}
void flush()
{
bool anyNew = false;
WriteLog (lsINFO, Validations) << "Flushing validations";
boost::mutex::scoped_lock sl(mValidationLock);
BOOST_FOREACH(u160_val_pair& it, mCurrentValidations)
{
if (it.second)
mStaleValidations.push_back(it.second);
anyNew = true;
}
mCurrentValidations.clear();
if (anyNew)
condWrite();
while (mWriting)
{
sl.unlock();
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
sl.lock();
}
WriteLog (lsDEBUG, Validations) << "Validations flushed";
}
void condWrite()
{
if (mWriting)
return;
mWriting = true;
theApp->getJobQueue().addJob(jtWRITE, "Validations::doWrite",
BIND_TYPE(&Validations::doWrite, this, P_1));
}
void doWrite(Job&)
{
LoadEvent::autoptr event(theApp->getJobQueue().getLoadEventAP(jtDISK, "ValidationWrite"));
boost::format insVal("INSERT INTO Validations "
"(LedgerHash,NodePubKey,SignTime,RawData) VALUES ('%s','%s','%u',%s);");
boost::mutex::scoped_lock sl(mValidationLock);
assert(mWriting);
while (!mStaleValidations.empty())
{
std::vector<SerializedValidation::pointer> vector;
vector.reserve(512);
mStaleValidations.swap(vector);
sl.unlock();
{
Database *db = theApp->getLedgerDB()->getDB();
ScopedLock dbl(theApp->getLedgerDB()->getDBLock());
Serializer s(1024);
db->executeSQL("BEGIN TRANSACTION;");
BOOST_FOREACH(SerializedValidation::ref it, vector)
{
s.erase();
it->add(s);
db->executeSQL(boost::str(insVal % it->getLedgerHash().GetHex()
% it->getSignerPublic().humanNodePublic() % it->getSignTime()
% sqlEscape(s.peekData())));
}
db->executeSQL("END TRANSACTION;");
}
sl.lock();
}
mWriting = false;
}
void sweep()
{
boost::mutex::scoped_lock sl(mValidationLock);
mValidations.sweep();
}
};
IValidations* IValidations::New ()
{
return new Validations;
}
// vim:ts=4