diff --git a/modules/ripple_ledger/ripple_ledger.cpp b/modules/ripple_ledger/ripple_ledger.cpp index d6b3edc7b..d314a8066 100644 --- a/modules/ripple_ledger/ripple_ledger.cpp +++ b/modules/ripple_ledger/ripple_ledger.cpp @@ -33,100 +33,6 @@ #include "ripple_ledger.h" -#include "../ripple_data/ripple_data.h" - -//#define WIN32_LEAN_AND_MEAN - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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) diff --git a/modules/ripple_ledger/ripple_ledger.h b/modules/ripple_ledger/ripple_ledger.h index 947a88c46..42ca20451 100644 --- a/modules/ripple_ledger/ripple_ledger.h +++ b/modules/ripple_ledger/ripple_ledger.h @@ -34,4 +34,98 @@ #include "modules/ripple_basics/ripple_basics.h" +#include "../ripple_data/ripple_data.h" + +//#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/modules/ripple_main/ripple_main.cpp b/modules/ripple_main/ripple_main.cpp index 98131f353..5bda2a5e6 100644 --- a/modules/ripple_main/ripple_main.cpp +++ b/modules/ripple_main/ripple_main.cpp @@ -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" diff --git a/modules/ripple_net/ripple_net.cpp b/modules/ripple_net/ripple_net.cpp index 17781cf69..289e4865a 100644 --- a/modules/ripple_net/ripple_net.cpp +++ b/modules/ripple_net/ripple_net.cpp @@ -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 diff --git a/newcoin.vcxproj b/newcoin.vcxproj index a69a49be2..96794c7b8 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -992,6 +992,12 @@ true true + + true + true + true + true + true true @@ -1178,12 +1184,6 @@ true true - - true - true - true - true - true true @@ -1656,6 +1656,7 @@ + @@ -1682,7 +1683,6 @@ - diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index 038d66780..27861eec7 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -618,9 +618,6 @@ 1. Modules\ripple_main\_old - - 1. Modules\ripple_main\_old - 1. Modules\ripple_main @@ -798,6 +795,9 @@ 1. Modules\ripple_ledger\main + + 1. Modules\ripple_ledger\main + @@ -1262,9 +1262,6 @@ 1. Modules\ripple_main\_old - - 1. Modules\ripple_main\_old - 1. Modules\ripple_main @@ -1484,6 +1481,9 @@ 1. Modules\ripple_ledger\main + + 1. Modules\ripple_ledger\main + diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index 2bdb435fe..c5e73f8a0 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -38,6 +38,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) @@ -76,7 +77,7 @@ void Application::stop() mShutdown = true; mIOService.stop(); mHashedObjectStore.waitWrite(); - mValidations.flush(); + mValidations->flush(); mAuxService.stop(); mJobQueue.shutdown(); @@ -234,7 +235,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)); @@ -391,7 +392,7 @@ void Application::sweep() mHashedObjectStore.sweep(); mLedgerMaster.sweep(); mTempNodeCache.sweep(); - mValidations.sweep(); + mValidations->sweep(); getMasterLedgerAcquire().sweep(); mSLECache.sweep(); AcceptedLedger::sweep(); @@ -403,8 +404,10 @@ void Application::sweep() Application::~Application() { + delete mValidations; delete mFeeTrack; delete mFeeVote; + delete mTxnDB; delete mLedgerDB; delete mWalletDB; diff --git a/src/cpp/ripple/Application.h b/src/cpp/ripple/Application.h index 622a76a53..90c8a4e88 100644 --- a/src/cpp/ripple/Application.h +++ b/src/cpp/ripple/Application.h @@ -19,7 +19,6 @@ #include "Peer.h" #include "NetworkOPs.h" #include "WSDoor.h" -#include "ValidationCollection.h" #include "Suppression.h" #include "SNTPClient.h" #include "JobQueue.h" @@ -35,6 +34,7 @@ class IFeatureTable; class IFeeVote; class ILoadFeeTrack; +class IValidations; class RPCDoor; class PeerDoor; @@ -55,7 +55,6 @@ class Application TransactionMaster mMasterTransaction; NetworkOPs mNetOps; NodeCache mTempNodeCache; - ValidationCollection mValidations; SuppressionTable mSuppressions; HashedObjectStore mHashedObjectStore; SLECache mSLECache; @@ -65,9 +64,14 @@ class Application LoadManager mLoadMgr; TXQueue mTxnQueue; OrderBookDB mOrderBookDB; - IFeeVote* mFeeVote; + + // VFALCO: Clean stuff + IFeeVote* mFeeVote; ILoadFeeTrack* mFeeTrack; - FeatureTable mFeatureTable; + IValidations* mValidations; + // VFALCO: End Clean stuff + + FeatureTable mFeatureTable; DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mNetNodeDB, *mPathFindDB, *mHashNodeDB; @@ -114,20 +118,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); } diff --git a/src/cpp/ripple/ValidationCollection.cpp b/src/cpp/ripple/ValidationCollection.cpp deleted file mode 100644 index 7862b4cd2..000000000 --- a/src/cpp/ripple/ValidationCollection.cpp +++ /dev/null @@ -1,353 +0,0 @@ - -#include "ValidationCollection.h" - -#include - -#include "Application.h" -#include "LedgerTiming.h" - -SETUP_LOG (ValidationCollection) - -typedef std::map::value_type u160_val_pair; -typedef boost::shared_ptr 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(); - 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::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 ValidationCollection::getCurrentTrustedValidations() -{ - uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL; - - std::list ret; - - boost::mutex::scoped_lock sl(mValidationLock); - boost::unordered_map::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 -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 ret; - - boost::mutex::scoped_lock sl(mValidationLock); - boost::unordered_map::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 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 diff --git a/src/cpp/ripple/ValidationCollection.h b/src/cpp/ripple/ValidationCollection.h deleted file mode 100644 index 0569c8bc3..000000000 --- a/src/cpp/ripple/ValidationCollection.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __VALIDATION_COLLECTION__ -#define __VALIDATION_COLLECTION__ - -#include - -#include -#include - -#include "SerializedValidation.h" -#include "JobQueue.h" - -typedef boost::unordered_map ValidationSet; - -typedef std::pair currentValidationCount; // nodes validating and highest node ID validating - -// VFALCO: TODO, Rename this to "Validations" -class ValidationCollection -{ -protected: - - boost::mutex mValidationLock; - TaggedCache mValidations; - boost::unordered_map mCurrentValidations; - std::vector mStaleValidations; - - bool mWriting; - - void doWrite(Job&); - void condWrite(); - - boost::shared_ptr findCreateSet(const uint256& ledgerHash); - boost::shared_ptr 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 getCurrentValidations( - uint256 currentLedger, uint256 previousLedger); - - std::list getCurrentTrustedValidations(); - - void tune(int size, int age); - void flush(); - void sweep(); -}; - -#endif diff --git a/src/cpp/ripple/ripple_IValidations.h b/src/cpp/ripple/ripple_IValidations.h new file mode 100644 index 000000000..02312001c --- /dev/null +++ b/src/cpp/ripple/ripple_IValidations.h @@ -0,0 +1,47 @@ +#ifndef RIPPLE_IVALIDATIONS_H +#define RIPPLE_IVALIDATIONS_H + +//#include +//#include +//#include + +//#include "SerializedValidation.h" +//#include "JobQueue.h" + +// VFALCO: TODO rename and move these typedefs into the IValidations interface +typedef boost::unordered_map ValidationSet; +typedef std::pair 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 getCurrentValidations ( + uint256 currentLedger, uint256 previousLedger) = 0; + + virtual std::list getCurrentTrustedValidations () = 0; + + virtual void tune (int size, int age) = 0; + + virtual void flush () = 0; + + virtual void sweep() = 0; +}; + +#endif diff --git a/src/cpp/ripple/ripple_Validations.cpp b/src/cpp/ripple/ripple_Validations.cpp new file mode 100644 index 000000000..4dea97ed5 --- /dev/null +++ b/src/cpp/ripple/ripple_Validations.cpp @@ -0,0 +1,377 @@ + +#include + +#include "Application.h" +#include "LedgerTiming.h" + +class Validations; + +SETUP_LOG (Validations) + +typedef std::map::value_type u160_val_pair; +typedef boost::shared_ptr VSpointer; + +class Validations : public IValidations +{ +private: + boost::mutex mValidationLock; + TaggedCache mValidations; + boost::unordered_map mCurrentValidations; + std::vector mStaleValidations; + + bool mWriting; + +private: + boost::shared_ptr findCreateSet(const uint256& ledgerHash) + { + VSpointer j = mValidations.fetch(ledgerHash); + if (!j) + { + j = boost::make_shared(); + mValidations.canonicalize(ledgerHash, j); + } + return j; + } + + boost::shared_ptr 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::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 getCurrentTrustedValidations() + { + uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL; + + std::list ret; + + boost::mutex::scoped_lock sl(mValidationLock); + boost::unordered_map::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 + getCurrentValidations(uint256 currentLedger, uint256 priorLedger) + { + uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL; + bool valCurrentLedger = currentLedger.isNonZero(); + bool valPriorLedger = priorLedger.isNonZero(); + + boost::unordered_map ret; + + boost::mutex::scoped_lock sl(mValidationLock); + boost::unordered_map::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 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