From 91e0cc84efb81d70a75b7b9a71b55d2876c90ad3 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 2 Sep 2013 18:23:45 -0700 Subject: [PATCH] Validators framework and unit test --- Builds/VisualStudio2012/RippleD.vcxproj | 21 +- .../VisualStudio2012/RippleD.vcxproj.filters | 87 ++-- .../ledger/SerializedValidation.cpp | 4 +- .../ripple_app/ledger/SerializedValidation.h | 5 +- .../ripple_app/main/ripple_Application.cpp | 21 +- modules/ripple_app/main/ripple_Application.h | 4 +- .../ripple_app/misc/ripple_Validations.cpp | 12 +- ...le_IValidations.h => ripple_Validations.h} | 12 +- modules/ripple_app/peers/ripple_Peer.cpp | 13 + modules/ripple_app/ripple_app.h | 2 +- .../ripple_basics/types/ripple_BasicTypes.h | 8 + modules/ripple_core/ripple_core.cpp | 13 +- modules/ripple_core/ripple_core.h | 6 +- .../{ripple_Validator.cpp => Validator.cpp} | 2 +- .../{ripple_Validator.h => Validator.h} | 23 +- .../validator/ValidatorSourceStrings.cpp | 34 ++ ...datorSource.h => ValidatorSourceStrings.h} | 8 +- .../validator/ValidatorSourceTrustedUri.cpp | 36 ++ ...orSource.h => ValidatorSourceTrustedUri.h} | 8 +- modules/ripple_core/validator/Validators.cpp | 209 ++++++++ modules/ripple_core/validator/Validators.h | 107 +++++ modules/ripple_core/validator/ValidatorsImp.h | 438 +++++++++++++++++ .../ripple_StringsValidatorSource.cpp | 29 -- .../ripple_TrustedUriValidatorSource.cpp | 31 -- .../validator/ripple_ValidatorImp.h | 12 - .../validator/ripple_ValidatorList.h | 10 - .../validator/ripple_Validators.cpp | 451 ------------------ .../ripple_core/validator/ripple_Validators.h | 69 --- 28 files changed, 948 insertions(+), 727 deletions(-) rename modules/ripple_app/misc/{ripple_IValidations.h => ripple_Validations.h} (84%) rename modules/ripple_core/validator/{ripple_Validator.cpp => Validator.cpp} (81%) rename modules/ripple_core/validator/{ripple_Validator.h => Validator.h} (87%) create mode 100644 modules/ripple_core/validator/ValidatorSourceStrings.cpp rename modules/ripple_core/validator/{ripple_StringsValidatorSource.h => ValidatorSourceStrings.h} (59%) create mode 100644 modules/ripple_core/validator/ValidatorSourceTrustedUri.cpp rename modules/ripple_core/validator/{ripple_TrustedUriValidatorSource.h => ValidatorSourceTrustedUri.h} (53%) create mode 100644 modules/ripple_core/validator/Validators.cpp create mode 100644 modules/ripple_core/validator/Validators.h create mode 100644 modules/ripple_core/validator/ValidatorsImp.h delete mode 100644 modules/ripple_core/validator/ripple_StringsValidatorSource.cpp delete mode 100644 modules/ripple_core/validator/ripple_TrustedUriValidatorSource.cpp delete mode 100644 modules/ripple_core/validator/ripple_ValidatorImp.h delete mode 100644 modules/ripple_core/validator/ripple_ValidatorList.h delete mode 100644 modules/ripple_core/validator/ripple_Validators.cpp delete mode 100644 modules/ripple_core/validator/ripple_Validators.h diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index 451ee87701..cd304a991e 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -778,25 +778,25 @@ true - + true true true true - + true true true true - + true true true true - + true true true @@ -1398,13 +1398,13 @@ - + @@ -1501,12 +1501,11 @@ - - - - - - + + + + + diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index 2fc020be3a..c4b8552b58 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -159,18 +159,6 @@ [0] Subtrees\protobuf - - [1] Ripple\ripple_app - - - [1] Ripple\ripple_app - - - [1] Ripple\ripple_app - - - [1] Ripple\ripple_app - [1] Ripple\ripple_basics\containers @@ -477,6 +465,18 @@ [0] Subtrees\leveldb\port + + [1] Ripple\ripple_app + + + [1] Ripple\ripple_app + + + [1] Ripple\ripple_app + + + [1] Ripple\ripple_app + [1] Ripple\ripple_app @@ -528,12 +528,6 @@ [1] Ripple\ripple_app\data - - [1] Ripple\ripple_core\validator - - - [1] Ripple\ripple_core\validator - [1] Ripple\ripple_app\ledger @@ -570,12 +564,6 @@ [1] Ripple\ripple_app\ledger - - [1] Ripple\ripple_core\validator - - - [1] Ripple\ripple_core\validator - [0] Subtrees\beast @@ -864,6 +852,18 @@ [1] Ripple\ripple_core\node + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + @@ -1286,12 +1286,6 @@ [1] Ripple\ripple_app\data - - [1] Ripple\ripple_core\validator - - - [1] Ripple\ripple_core\validator - [1] Ripple\ripple_app\ledger @@ -1328,15 +1322,6 @@ [1] Ripple\ripple_app\ledger - - [1] Ripple\ripple_core\validator - - - [1] Ripple\ripple_core\validator - - - [1] Ripple\ripple_core\validator - [1] Ripple\ripple_core\functional @@ -1373,9 +1358,6 @@ [1] Ripple\ripple_app\misc - - [1] Ripple\ripple_app\misc - [1] Ripple\ripple_app\misc @@ -1499,9 +1481,6 @@ [1] Ripple\ripple_app\tx - - [1] Ripple\ripple_core\validator - [1] Ripple\ripple_app\main @@ -1688,6 +1667,24 @@ [1] Ripple\ripple_core\node + + [1] Ripple\ripple_app\misc + + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + + + [1] Ripple\ripple_core\validator + diff --git a/modules/ripple_app/ledger/SerializedValidation.cpp b/modules/ripple_app/ledger/SerializedValidation.cpp index 31996d1814..10fe4aa2f2 100644 --- a/modules/ripple_app/ledger/SerializedValidation.cpp +++ b/modules/ripple_app/ledger/SerializedValidation.cpp @@ -33,7 +33,7 @@ SerializedValidation::SerializedValidation ( assert (mNodeID.isNonZero ()); if (!isFull) - setFlag (sFullFlag); + setFlag (kFullFlag); } void SerializedValidation::sign (const RippleAddress& raPriv) @@ -98,7 +98,7 @@ RippleAddress SerializedValidation::getSignerPublic () const bool SerializedValidation::isFull () const { - return (getFlags () & sFullFlag) != 0; + return (getFlags () & kFullFlag) != 0; } Blob SerializedValidation::getSignature () const diff --git a/modules/ripple_app/ledger/SerializedValidation.h b/modules/ripple_app/ledger/SerializedValidation.h index e4aaed02e0..64618ea5ea 100644 --- a/modules/ripple_app/ledger/SerializedValidation.h +++ b/modules/ripple_app/ledger/SerializedValidation.h @@ -17,7 +17,10 @@ public: typedef boost::shared_ptr pointer; typedef const boost::shared_ptr& ref; - static const uint32 sFullFlag = 0x1; + enum + { + kFullFlag = 0x1 + }; // These throw if the object is not valid SerializedValidation (SerializerIterator & sit, bool checkSignature = true); diff --git a/modules/ripple_app/main/ripple_Application.cpp b/modules/ripple_app/main/ripple_Application.cpp index 33f359d545..c4158229e0 100644 --- a/modules/ripple_app/main/ripple_Application.cpp +++ b/modules/ripple_app/main/ripple_Application.cpp @@ -15,7 +15,6 @@ SETUP_LOG (Application) class ApplicationImp : public Application , public SharedSingleton - , public Validators::Listener , public NodeStore::Scheduler , LeakChecked { @@ -168,12 +167,12 @@ public: getConfig ().nodeDatabase, getConfig ().ephemeralNodeDatabase, *this)) - , m_validators (Validators::New (this)) + , m_validators (Validators::New ()) , mFeatures (IFeatures::New (2 * 7 * 24 * 60 * 60, 200)) // two weeks, 200/256 , mFeeVote (IFeeVote::New (10, 50 * SYSTEM_CURRENCY_PARTS, 12.5 * SYSTEM_CURRENCY_PARTS)) , mFeeTrack (ILoadFeeTrack::New ()) , mHashRouter (IHashRouter::New (IHashRouter::getDefaultHoldTime ())) - , mValidations (IValidations::New ()) + , mValidations (Validations::New ()) , mUNL (UniqueNodeList::New ()) , mProofOfWorkFactory (ProofOfWorkFactory::New ()) , m_loadManager (LoadManager::New ()) @@ -313,7 +312,7 @@ public: return *mHashRouter; } - IValidations& getValidations () + Validations& getValidations () { return *mValidations; } @@ -697,7 +696,7 @@ private: ScopedPointer mFeeVote; ScopedPointer mFeeTrack; ScopedPointer mHashRouter; - ScopedPointer mValidations; + ScopedPointer mValidations; ScopedPointer mUNL; ScopedPointer mProofOfWorkFactory; ScopedPointer m_peers; @@ -819,43 +818,33 @@ void ApplicationImp::doSweep(Job& j) logTimedCall ("TransactionMaster::sweep", __FILE__, __LINE__, boost::bind ( &TransactionMaster::sweep, &mMasterTransaction)); - //mMasterTransaction.sweep (); logTimedCall ("NodeStore::sweep", __FILE__, __LINE__, boost::bind ( &NodeStore::sweep, m_nodeStore.get ())); - //m_nodeStore->sweep (); logTimedCall ("LedgerMaster::sweep", __FILE__, __LINE__, boost::bind ( &LedgerMaster::sweep, &m_ledgerMaster)); - //m_ledgerMaster.sweep (); logTimedCall ("TempNodeCache::sweep", __FILE__, __LINE__, boost::bind ( &NodeCache::sweep, &mTempNodeCache)); - //mTempNodeCache.sweep (); logTimedCall ("Validations::sweep", __FILE__, __LINE__, boost::bind ( - &IValidations::sweep, mValidations.get ())); - //mValidations->sweep (); + &Validations::sweep, mValidations.get ())); logTimedCall ("InboundLedgers::sweep", __FILE__, __LINE__, boost::bind ( &InboundLedgers::sweep, &getInboundLedgers ())); - //getInboundLedgers ().sweep (); logTimedCall ("SLECache::sweep", __FILE__, __LINE__, boost::bind ( &SLECache::sweep, &mSLECache)); - //mSLECache.sweep (); logTimedCall ("AcceptedLedger::sweep", __FILE__, __LINE__, &AcceptedLedger::sweep); - //AcceptedLedger::sweep (); // VFALCO NOTE AcceptedLedger is/has a singleton? logTimedCall ("SHAMap::sweep", __FILE__, __LINE__, &SHAMap::sweep); - //SHAMap::sweep (); // VFALCO NOTE SHAMap is/has a singleton? logTimedCall ("NetworkOPs::sweepFetchPack", __FILE__, __LINE__, boost::bind ( &NetworkOPs::sweepFetchPack, m_networkOPs.get ())); - //m_networkOPs->sweepFetchPack (); // VFALCO NOTE does the call to sweep() happen on another thread? mSweepTimer.expires_from_now (boost::posix_time::seconds (getConfig ().getSize (siSweepInterval))); diff --git a/modules/ripple_app/main/ripple_Application.h b/modules/ripple_app/main/ripple_Application.h index a4cd1422d1..1a9273934d 100644 --- a/modules/ripple_app/main/ripple_Application.h +++ b/modules/ripple_app/main/ripple_Application.h @@ -14,7 +14,6 @@ class IHashRouter; class ILoadFeeTrack; class Peers; class UniqueNodeList; -class IValidations; class Validators; class NodeStore; @@ -86,8 +85,7 @@ public: virtual Peers& getPeers () = 0; virtual ProofOfWorkFactory& getProofOfWorkFactory () = 0; virtual UniqueNodeList& getUNL () = 0; - virtual IValidations& getValidations () = 0; - + virtual Validations& getValidations () = 0; virtual NodeStore& getNodeStore () = 0; virtual JobQueue& getJobQueue () = 0; virtual InboundLedgers& getInboundLedgers () = 0; diff --git a/modules/ripple_app/misc/ripple_Validations.cpp b/modules/ripple_app/misc/ripple_Validations.cpp index c6347fd973..5f08479230 100644 --- a/modules/ripple_app/misc/ripple_Validations.cpp +++ b/modules/ripple_app/misc/ripple_Validations.cpp @@ -4,14 +4,14 @@ */ //============================================================================== -class Validations; +class ValidationsImp; SETUP_LOG (Validations) typedef std::map::value_type u160_val_pair; typedef boost::shared_ptr VSpointer; -class Validations : public IValidations +class ValidationsImp : public Validations { private: typedef RippleMutex LockType; @@ -45,7 +45,7 @@ private: } public: - Validations () + ValidationsImp () : mLock (this, "Validations", __FILE__, __LINE__) , mValidations ("Validations", 128, 600), mWriting (false) { @@ -394,7 +394,7 @@ private: mWriting = true; getApp().getJobQueue ().addJob (jtWRITE, "Validations::doWrite", - BIND_TYPE (&Validations::doWrite, this, P_1)); + BIND_TYPE (&ValidationsImp::doWrite, this, P_1)); } void doWrite (Job&) @@ -443,9 +443,9 @@ private: } }; -IValidations* IValidations::New () +Validations* Validations::New () { - return new Validations; + return new ValidationsImp; } // vim:ts=4 diff --git a/modules/ripple_app/misc/ripple_IValidations.h b/modules/ripple_app/misc/ripple_Validations.h similarity index 84% rename from modules/ripple_app/misc/ripple_IValidations.h rename to modules/ripple_app/misc/ripple_Validations.h index 38e338776d..6f1e797ff7 100644 --- a/modules/ripple_app/misc/ripple_IValidations.h +++ b/modules/ripple_app/misc/ripple_Validations.h @@ -4,19 +4,19 @@ */ //============================================================================== -#ifndef RIPPLE_IVALIDATIONS_H -#define RIPPLE_IVALIDATIONS_H +#ifndef RIPPLE_VALIDATIONS_H_INCLUDED +#define RIPPLE_VALIDATIONS_H_INCLUDED -// VFALCO TODO rename and move these typedefs into the IValidations interface +// VFALCO TODO rename and move these typedefs into the Validations interface typedef boost::unordered_map ValidationSet; typedef std::pair currentValidationCount; // nodes validating and highest node ID validating -class IValidations : LeakChecked +class Validations : LeakChecked { public: - static IValidations* New (); + static Validations* New (); - virtual ~IValidations () { } + virtual ~Validations () { } virtual bool addValidation (SerializedValidation::ref, const std::string& source) = 0; diff --git a/modules/ripple_app/peers/ripple_Peer.cpp b/modules/ripple_app/peers/ripple_Peer.cpp index dc268181fb..ee42555e89 100644 --- a/modules/ripple_app/peers/ripple_Peer.cpp +++ b/modules/ripple_app/peers/ripple_Peer.cpp @@ -1468,6 +1468,19 @@ static void checkValidation (Job&, SerializedValidation::pointer val, bool isTru std::set peers; + //---------------------------------------------------------------------- + // + { + SerializedValidation const& sv (*val); + Validators::ReceivedValidation rv; + rv.ledgerHash = sv.getLedgerHash (); + uint160 const publicKeyHash (sv.getSignerPublic ().getNodeID ()); + rv.signerPublicKeyHash = RipplePublicKeyHash (publicKeyHash.begin ()); + getApp ().getValidators ().receiveValidation (rv); + } + // + //---------------------------------------------------------------------- + if (getApp().getOPs ().recvValidation (val, source) && getApp().getHashRouter ().swapSet (signingHash, peers, SF_RELAYED)) { diff --git a/modules/ripple_app/ripple_app.h b/modules/ripple_app/ripple_app.h index 93806e3b31..389afebcf7 100644 --- a/modules/ripple_app/ripple_app.h +++ b/modules/ripple_app/ripple_app.h @@ -78,7 +78,7 @@ namespace ripple #include "peers/ripple_Peers.h" #include "peers/ripple_ClusterNodeStatus.h" #include "peers/ripple_UniqueNodeList.h" -#include "misc/ripple_IValidations.h" +#include "misc/ripple_Validations.h" #include "peers/ripple_PeerSet.h" #include "ledger/ripple_InboundLedger.h" #include "ledger/ripple_InboundLedgers.h" diff --git a/modules/ripple_basics/types/ripple_BasicTypes.h b/modules/ripple_basics/types/ripple_BasicTypes.h index 4a46276ab5..2574c4e804 100644 --- a/modules/ripple_basics/types/ripple_BasicTypes.h +++ b/modules/ripple_basics/types/ripple_BasicTypes.h @@ -27,4 +27,12 @@ typedef UntrackedMutexType RippleRecursiveMutex; typedef boost::recursive_mutex DeprecatedRecursiveMutex; typedef DeprecatedRecursiveMutex::scoped_lock DeprecatedScopedLock; +//------------------------------------------------------------------------------ + +/** A container used to hold a public key in binary format. */ +typedef UnsignedInteger <33> RipplePublicKey; + +/** A container holding the hash of a public key in binary format. */ +typedef UnsignedInteger <20> RipplePublicKeyHash; + #endif diff --git a/modules/ripple_core/ripple_core.cpp b/modules/ripple_core/ripple_core.cpp index 60dd5f4f33..e01ad29990 100644 --- a/modules/ripple_core/ripple_core.cpp +++ b/modules/ripple_core/ripple_core.cpp @@ -46,10 +46,13 @@ namespace ripple #include "node/NodeStore.cpp" #include "node/NodeObject.cpp" -#include "validator/ripple_Validator.cpp" -#include "validator/ripple_ValidatorImp.h" // private -#include "validator/ripple_Validators.cpp" -#include "validator/ripple_StringsValidatorSource.cpp" -#include "validator/ripple_TrustedUriValidatorSource.cpp" +# include "validator/Validator.h" +#include "validator/Validator.cpp" +# include "validator/ValidatorSourceStrings.h" +# include "validator/ValidatorSourceTrustedUri.h" +# include "validator/ValidatorsImp.h" // private +#include "validator/ValidatorSourceStrings.cpp" +#include "validator/ValidatorSourceTrustedUri.cpp" +#include "validator/Validators.cpp" } diff --git a/modules/ripple_core/ripple_core.h b/modules/ripple_core/ripple_core.h index a96dc375fd..3cbe914455 100644 --- a/modules/ripple_core/ripple_core.h +++ b/modules/ripple_core/ripple_core.h @@ -28,11 +28,7 @@ namespace ripple #include "node/NodeObject.h" #include "node/NodeStore.h" -#include "validator/ripple_Validator.h" -#include "validator/ripple_ValidatorList.h" -#include "validator/ripple_Validators.h" -#include "validator/ripple_StringsValidatorSource.h" -#include "validator/ripple_TrustedUriValidatorSource.h" +#include "validator/Validators.h" } diff --git a/modules/ripple_core/validator/ripple_Validator.cpp b/modules/ripple_core/validator/Validator.cpp similarity index 81% rename from modules/ripple_core/validator/ripple_Validator.cpp rename to modules/ripple_core/validator/Validator.cpp index 0766d0c7f3..2a3913a277 100644 --- a/modules/ripple_core/validator/ripple_Validator.cpp +++ b/modules/ripple_core/validator/Validator.cpp @@ -4,7 +4,7 @@ */ //============================================================================== -Validator::Validator (PublicKey const& publicKey) +Validator::Validator (RipplePublicKey const& publicKey) : m_publicKey (publicKey) { } diff --git a/modules/ripple_core/validator/ripple_Validator.h b/modules/ripple_core/validator/Validator.h similarity index 87% rename from modules/ripple_core/validator/ripple_Validator.h rename to modules/ripple_core/validator/Validator.h index c69ca2ea97..1296bfca1e 100644 --- a/modules/ripple_core/validator/ripple_Validator.h +++ b/modules/ripple_core/validator/Validator.h @@ -4,8 +4,8 @@ */ //============================================================================== -#ifndef RIPPLE_VALIDATOR_H_INCLUDED -#define RIPPLE_VALIDATOR_H_INCLUDED +#ifndef RIPPLE_CORE_VALIDATOR_VALIDATOR_H_INCLUDED +#define RIPPLE_CORE_VALIDATOR_VALIDATOR_H_INCLUDED //------------------------------------------------------------------------------ @@ -18,6 +18,8 @@ class Validator : public SharedObject { public: + typedef SharedObjectPtr Ptr; + /** Fixed information on a validator. This describes a validator. @@ -41,12 +43,7 @@ public: } }; - // VFALCO TODO magic number argh!!! - // This type should be located elsewhere. - // - typedef UnsignedInteger <33> PublicKey; - - PublicKey publicKey; + RipplePublicKey publicKey; //String friendlyName; //String organizationType; //String jurisdicton; @@ -74,10 +71,6 @@ public: } }; - typedef SharedObjectPtr Ptr; - - typedef Info::PublicKey PublicKey; - //-------------------------------------------------------------------------- // Comparison function for Validator objects @@ -135,12 +128,12 @@ public: //-------------------------------------------------------------------------- - explicit Validator (PublicKey const& publicKey); + explicit Validator (RipplePublicKey const& publicKey); - PublicKey const& getPublicKey () const { return m_publicKey; } + RipplePublicKey const& getPublicKey () const { return m_publicKey; } private: - PublicKey const m_publicKey; + RipplePublicKey const m_publicKey; }; diff --git a/modules/ripple_core/validator/ValidatorSourceStrings.cpp b/modules/ripple_core/validator/ValidatorSourceStrings.cpp new file mode 100644 index 0000000000..1c987f4b96 --- /dev/null +++ b/modules/ripple_core/validator/ValidatorSourceStrings.cpp @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +class ValidatorSourceStringsImp : public ValidatorSourceStrings +{ +public: + ValidatorSourceStringsImp (StringArray const& strings) + { + } + + ~ValidatorSourceStringsImp () + { + } + + Array fetch (CancelCallback&) + { + return Array (); + } + +private: +}; + +//------------------------------------------------------------------------------ + +ValidatorSourceStrings* ValidatorSourceStrings::New (StringArray const& strings) +{ + ScopedPointer object ( + new ValidatorSourceStringsImp (strings)); + + return object.release (); +} diff --git a/modules/ripple_core/validator/ripple_StringsValidatorSource.h b/modules/ripple_core/validator/ValidatorSourceStrings.h similarity index 59% rename from modules/ripple_core/validator/ripple_StringsValidatorSource.h rename to modules/ripple_core/validator/ValidatorSourceStrings.h index d7991a7d4f..df1e04e364 100644 --- a/modules/ripple_core/validator/ripple_StringsValidatorSource.h +++ b/modules/ripple_core/validator/ValidatorSourceStrings.h @@ -4,17 +4,17 @@ */ //============================================================================== -#ifndef RIPPLE_STRINGSVALIDATORSOURCE_H_INCLUDED -#define RIPPLE_STRINGSVALIDATORSOURCE_H_INCLUDED +#ifndef RIPPLE_CORE_VALIDATOR_VALIDATORSOURCESTRINGS_H_INCLUDED +#define RIPPLE_CORE_VALIDATOR_VALIDATORSOURCESTRINGS_H_INCLUDED /** Provides validators from a set of Validator strings. Typically this will come from a local configuration file. */ -class StringsValidatorSource : public Validators::Source +class ValidatorSourceStrings : public Validators::Source { public: - static StringsValidatorSource* New (StringArray const& strings); + static ValidatorSourceStrings* New (StringArray const& strings); }; #endif diff --git a/modules/ripple_core/validator/ValidatorSourceTrustedUri.cpp b/modules/ripple_core/validator/ValidatorSourceTrustedUri.cpp new file mode 100644 index 0000000000..67b26f569a --- /dev/null +++ b/modules/ripple_core/validator/ValidatorSourceTrustedUri.cpp @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +class ValidatorSourceTrustedUriImp : public ValidatorSourceTrustedUri +{ +public: + explicit ValidatorSourceTrustedUriImp (String const& uri) + : m_uri (uri) + { + } + + ~ValidatorSourceTrustedUriImp () + { + } + + Array fetch (CancelCallback&) + { + return Array (); + } + +private: + String const m_uri; +}; + +//------------------------------------------------------------------------------ + +ValidatorSourceTrustedUri* ValidatorSourceTrustedUri::New (String const& uri) +{ + ScopedPointer object ( + new ValidatorSourceTrustedUriImp (uri)); + + return object.release (); +} diff --git a/modules/ripple_core/validator/ripple_TrustedUriValidatorSource.h b/modules/ripple_core/validator/ValidatorSourceTrustedUri.h similarity index 53% rename from modules/ripple_core/validator/ripple_TrustedUriValidatorSource.h rename to modules/ripple_core/validator/ValidatorSourceTrustedUri.h index 5a32f2a211..5f5ea0087e 100644 --- a/modules/ripple_core/validator/ripple_TrustedUriValidatorSource.h +++ b/modules/ripple_core/validator/ValidatorSourceTrustedUri.h @@ -4,15 +4,15 @@ */ //============================================================================== -#ifndef RIPPLE_TRUSTEDURIVALIDATORSOURCE_H_INCLUDED -#define RIPPLE_TRUSTEDURIVALIDATORSOURCE_H_INCLUDED +#ifndef RIPPLE_CORE_VALIDATOR_VALIDATORSOURCETRUSTEDURI_H_INCLUDED +#define RIPPLE_CORE_VALIDATOR_VALIDATORSOURCETRUSTEDURI_H_INCLUDED /** Provides validators from a trusted URI (e.g. HTTPS) */ -class TrustedUriValidatorSource : public Validators::Source +class ValidatorSourceTrustedUri : public Validators::Source { public: - static TrustedUriValidatorSource* New (String url); + static ValidatorSourceTrustedUri* New (String const& uri); }; #endif diff --git a/modules/ripple_core/validator/Validators.cpp b/modules/ripple_core/validator/Validators.cpp new file mode 100644 index 0000000000..036971df4a --- /dev/null +++ b/modules/ripple_core/validator/Validators.cpp @@ -0,0 +1,209 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +/* + +Goal: + + Provide the listener with a ValidatorList. + - This forms the UNL + +Task: + + fetch ValidatorInfo array from a source + + - We have the old one and the new one, compute the following: + + * unchanged validators list + * new validators list + * removed validators list + + - From the unchanged / new / removed, figure out what to do. + +Two important questions: + +- Are there any validators in my ChosenValidators that I dont want + * For example, they have dropped off all the trusted lists + +- Do I have enough? + +-------------------------------------------------------------------------------- +ChosenValidators +-------------------------------------------------------------------------------- + +David: + I've cut 2 of the 6 active client-facing servers to hyper. Since then, we've + had 5 spinouts on 3 servers, none of them on the 2 I've cut over. But they + are also the most recently restarted servers, so it's not a 100% fair test. + + Maybe OC should have a URL that you can query to get the latest list of URI's + for OC-approved organzations that publish lists of validators. The server and + client can ship with that master trust URL and also the list of URI's at the + time it's released, in case for some reason it can't pull from OC. That would + make the default installation safe even against major changes in the + organizations that publish validator lists. + + The difference is that if an organization that provides lists of validators + goes rogue, administrators don't have to act. + +TODO: + Write up from end-user perspective on the deployment and administration + of this feature, on the wiki. "DRAFT" or "PROPOSE" to mark it as provisional. + Template: https://ripple.com/wiki/Federation_protocol + - What to do if you're a publisher of ValidatorList + - What to do if you're a rippled administrator + - Overview of how ChosenValidators works + + +Goals: + Make default configuration of rippled secure. + * Ship with TrustedUriList + * Also have a preset RankedValidators + Eliminate administrative burden of maintaining + Produce the ChosenValidators list. + Allow quantitative analysis of network health. + +What determines that a validator is good? + - Are they present (i.e. sending validations) + - Are they on the consensus ledger + - What percentage of consensus rounds do they participate in + - Are they stalling consensus + * Measurements of constructive/destructive behavior is + calculated in units of percentage of ledgers for which + the behavior is measured. + +Nouns + + Validator + - Signs ledgers and participate in consensus + - Fields + * Public key + * Friendly name + * Jurisdiction + * Org type: profit, nonprofit, "profit/gateway" + - Metadata + * Visible on the network? + * On the consensus ledger? + * Percentage of recent participation in consensus + * Frequency of stalling the consensus process + + ValidatorSource + - Abstract + - Provides a list of Validator + + ValidatorList + - Essentially an array of Validator + + ValidatorSourceTrustedUri + - ValidatorSource which uses HTTPS and a predefined URI + - Domain owner is responsible for removing bad validators + + ValidatorSourceTrustedUri::List + - Essentially an array of ValidatorSourceTrustedUri + - Can be read from a file + + LocalFileValidatorSource + - ValidatorSource which reads information from a local file. + + TrustedUriList // A copy of this ships with the app + * has a KnownValidators + + KnownValidators + * A series of KnownValidator that comes from a TrustedUri + * Persistent storage has a timestamp + + RankedValidators + * Created as the union of all KnownValidators with "weight" being the + number of appearances. + + ChosenValidators + * Result of the algorithm that chooses a random subset of RankedKnownValidators + * "local health" percentage is the percent of validations from this list that + you've seen recently. And have they been behaving. +*/ + +//------------------------------------------------------------------------------ + +Validators* Validators::New () +{ + return new ValidatorsImp (nullptr); +} + +//------------------------------------------------------------------------------ + +class ValidatorsTests : public UnitTest +{ +public: + enum + { + numberOfTestValidators = 1000 + }; + + struct TestSource : Validators::Source + { + TestSource (String const& name, uint32 start, uint32 end) + : m_name (name) + , m_start (start) + , m_end (end) + { + } + + Array fetch (CancelCallback& cancel) + { + Array list; + list.ensureStorageAllocated (numberOfTestValidators); + for (uint32 i = m_start ; i < m_end; ++i) + { + Info info; + info.key = Validators::KeyType::createFromInteger (i); + list.add (info); + } + return list; + } + + String m_name; + std::size_t m_start; + std::size_t m_end; + }; + + //-------------------------------------------------------------------------- + + void addSources (ValidatorsImp::Logic& logic) + { + logic.addSource (new TestSource ("source 1", 0, 1000)); + logic.addSource (new TestSource ("source 2", 200, 1500)); + logic.addSource (new TestSource ("source 3", 500, 2000)); + logic.addSource (new TestSource ("source 4", 750, 2200)); + logic.addSource (new TestSource ("source 5", 1500, 3200)); + } + + void testLogic () + { + beginTestCase ("logic"); + + ValidatorsImp::Logic logic; + addSources (logic); + + ValidatorsImp::NoOpCancelCallback cancelCallback; + logic.checkSources (cancelCallback); + + ValidatorsImp::ChosenList::Ptr list (logic.getChosenList ()); + + pass (); + } + + void runTest () + { + testLogic (); + } + + ValidatorsTests () : UnitTest ("Validators", "ripple", runManual) + { + } +}; + +static ValidatorsTests validatorsTests; + diff --git a/modules/ripple_core/validator/Validators.h b/modules/ripple_core/validator/Validators.h new file mode 100644 index 0000000000..a93e708015 --- /dev/null +++ b/modules/ripple_core/validator/Validators.h @@ -0,0 +1,107 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_CORE_VALIDATOR_VALIDATORS_H_INCLUDED +#define RIPPLE_CORE_VALIDATOR_VALIDATORS_H_INCLUDED + +/** Maintains the list of chosen validators. + + The algorithm for acquiring, building, and calculating metadata on + the list of chosen validators is critical to the health of the network. + + All operations are performed asynchronously on an internal thread. +*/ +class Validators : public Uncopyable +{ +public: + typedef RipplePublicKeyHash KeyType; + + //-------------------------------------------------------------------------- + + /** A source of validator descriptors. */ + class Source + { + public: + /** A Source's descriptor for a Validator. */ + struct Info + { + /** The unique key for this validator. */ + KeyType key; + }; + + /** Destroy the Source. + This can be called from any thread. If the Source is busy + fetching, the destructor must block until the operation is either + canceled or complete. + */ + virtual ~Source () { } + + struct CancelCallback + { + virtual bool shouldCancel () = 0; + }; + + /** Fetch the most recent list from the Source. + If possible, the Source should periodically poll the + CancelCallback, and abort the operation if shouldCancel + returns `true`. + This call will block. + */ + virtual Array fetch (CancelCallback& callback) = 0; + }; + + //-------------------------------------------------------------------------- + + /** Create a new Validators object. + */ + static Validators* New (); + + /** Destroy the object. + + Any pending source fetch operations are aborted. + + There may be some listener calls made before the + destructor returns. + */ + virtual ~Validators () { } + + /** Add a live source of validators. + The caller loses ownership of the object. + Thread safety: + Can be called from any thread. + */ + virtual void addSource (Source* source) = 0; + + /** Add a static source of validators. + The Source is called to fetch once and the results are kept + permanently. The fetch is performed asynchronously, this call + returns immediately. If the fetch fails, it is not reattempted. + The caller loses ownership of the object. + Thread safety: + Can be called from any thread. + */ + virtual void addStaticSource (Source* source) = 0; + + //-------------------------------------------------------------------------- + + // Trusted Validators + + //virtual bool isPublicKeyTrusted (Validator::PublicKey const&) = 0; + + //-------------------------------------------------------------------------- + + struct ReceivedValidation + { + uint256 ledgerHash; + RipplePublicKeyHash signerPublicKeyHash; + }; + + /** Called when a validation with a proper signature is received. + */ + virtual void receiveValidation (ReceivedValidation const& rv) = 0; +}; + +#endif diff --git a/modules/ripple_core/validator/ValidatorsImp.h b/modules/ripple_core/validator/ValidatorsImp.h new file mode 100644 index 0000000000..423c66e593 --- /dev/null +++ b/modules/ripple_core/validator/ValidatorsImp.h @@ -0,0 +1,438 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_CORE_VALIDATOR_VALIDATORSIMP_H_INCLUDED +#define RIPPLE_CORE_VALIDATOR_VALIDATORSIMP_H_INCLUDED + +// private implementation + +class ValidatorsImp + : public Validators + , private ThreadWithCallQueue::EntryPoints + , private DeadlineTimer::Listener + , LeakChecked +{ +public: + // Tunable constants + enum + { + // We will fetch a source at this interval + hoursBetweenFetches = 24 + + ,secondsBetweenFetches = hoursBetweenFetches * 60 * 60 + + // Wake up every hour to check source times + ,secondsPerUpdate = 60 * 60 + + // This tunes the preallocated arrays + ,expectedNumberOfResults = 1000 + }; + + //-------------------------------------------------------------------------- + + // Dummy CancelCallback that does nothing + // + struct NoOpCancelCallback : Source::CancelCallback + { + bool shouldCancel () + { + return false; + } + + }; + + //-------------------------------------------------------------------------- + + /** Receive event notifications on Validators operations. + */ + class Listener + { + public: + }; + + //-------------------------------------------------------------------------- + + class ChosenList : public SharedObject + { + public: + typedef SharedObjectPtr Ptr; + + struct Info + { + Info () + { + } + }; + + typedef HashMap MapType; + + ChosenList () + { + } + + std::size_t size () const noexcept + { + return m_map.size (); + } + + void insert (KeyType const& key, Info const& info) noexcept + { + m_map [key] = info; + } + + bool contains (KeyType const& key) const noexcept + { + return m_map.find (key) != m_map.cend (); + } + + private: + MapType m_map; + }; + + //-------------------------------------------------------------------------- + + // Encapsulates the logic for creating the chosen validators. + // This is a separate class to facilitate the unit tests. + // + class Logic + { + public: + // Information associated with each Source + // + struct SourceInfo + { + enum + { + keysPreallocationSize = 1000 + }; + + enum Status + { + statusNone, + statusFetched, + statusFailed + }; + + ScopedPointer source; + Status status; + Time whenToFetch; + int numberOfFailures; + + // The result of hte last fetch + Array list; + + //------------------------------------------------------------------ + + SourceInfo () noexcept + : status (statusNone) + , whenToFetch (Time::getCurrentTime ()) + , numberOfFailures (0) + { + list.ensureStorageAllocated (keysPreallocationSize); + } + + ~SourceInfo () + { + } + }; + + typedef DynamicList SourcesType; + + //---------------------------------------------------------------------- + + // Information associated with each distinguishable validator + // + struct ValidatorInfo + { + ValidatorInfo () + : refCount (0) + { + } + + KeyType key; + int refCount; + }; + + typedef HashMap MapType; + + //---------------------------------------------------------------------- + + Logic () + : m_chosenListNeedsUpdate (false) + { + } + + // Add a live source to the list of sources. + // + void addSource (Source* source) + { + SourceInfo& info (*m_sources.emplace_back ()); + info.source = source; + } + + // Add a one-time static source. + // Fetch is called right away, this call blocks. + // + void addStaticSource (Source* source) + { + ScopedPointer object (source); + + NoOpCancelCallback cancelCallback; + + Array list (object->fetch (cancelCallback)); + + addSourceInfo (list); + } + + // Called when we receive a validation from a peer. + // + void receiveValidation (Validators::ReceivedValidation const& rv) + { + MapType::iterator iter (m_map.find (rv.signerPublicKeyHash)); + if (iter != m_map.end ()) + { + // Exists + //ValidatorInfo& validatorInfo (iter->value ()); + } + else + { + // New + //ValidatorInfo& validatorInfo (m_map.insert (rv.signerPublicKeyHash)); + } + } + + // Add each entry in the list to the map, incrementing the + // reference count if it already exists, and updating fields. + // + void addSourceInfo (Array const& list) + { + for (std::size_t i = 0; i < list.size (); ++i) + { + Source::Info const& info (list.getReference (i)); + MapType::Result result (m_map.insert (info.key)); + ValidatorInfo& validatorInfo (result.iter->value ()); + ++validatorInfo.refCount; + if (result.inserted) + { + // This is a new one + markDirtyChosenList (); + } + } + } + + // Decrement the reference count of each item in the list + // in the map + // + void removeSourceInfo (Array const& list) + { + for (std::size_t i = 0; i < list.size (); ++i) + { + Source::Info const& info (list.getReference (i)); + MapType::iterator iter (m_map.find (info.key)); + bassert (iter != m_map.end ()); + ValidatorInfo& validatorInfo (iter->value ()); + if (--validatorInfo.refCount == 0) + { + // Last reference removed + m_map.erase (info.key); + markDirtyChosenList (); + } + } + } + + // Fetch one source + // + void fetchSource (SourceInfo& info, Source::CancelCallback& callback) + { + Array list (info.source->fetch (callback)); + if (! callback.shouldCancel ()) + { + // Reset fetch timer for the source. + info.whenToFetch = Time::getCurrentTime () + + RelativeTime (secondsBetweenFetches); + + // Add the new source info to the map + addSourceInfo (list); + + // Swap lists + info.list.swapWith (list); + + // Remove the old source info from the map + removeSourceInfo (list); + + // See if we need to rebuild + checkDirtyChosenList (); + } + } + + // Check each source to see if it needs fetching. + // + void checkSources (Source::CancelCallback& callback) + { + Time const currentTime (Time::getCurrentTime ()); + for (SourcesType::iterator iter = m_sources.begin (); + ! callback.shouldCancel () && iter != m_sources.end (); ++iter) + { + SourceInfo& info (*iter); + if (info.whenToFetch <= currentTime) + fetchSource (info, callback); + } + } + + // Signal that the Chosen List needs to be rebuilt. + // + void markDirtyChosenList () + { + m_chosenListNeedsUpdate = true; + } + + // Check the dirty state of the Chosen List, and rebuild it + // if necessary. + // + void checkDirtyChosenList () + { + if (m_chosenListNeedsUpdate) + { + buildChosenList (); + m_chosenListNeedsUpdate = false; + } + } + + // Rebuilds the Chosen List + // + void buildChosenList () + { + ChosenList::Ptr list (new ChosenList); + + for (MapType::iterator iter = m_map.begin (); + iter != m_map.end (); ++iter) + { + //ValidatorInfo const& validatorInfo (iter->value ()); + ChosenList::Info info; + list->insert (iter->key (), info); + } + + // This is thread safe + m_chosenList = list; + } + + // Get a reference to the chosen list. + // This is safe to call from any thread at any time. + // + ChosenList::Ptr getChosenList () + { + return m_chosenList; + } + + //---------------------------------------------------------------------- + // + // Ripple interface + // + // These routines are modeled after UniqueNodeList + + bool isTrustedPublicKeyHash (RipplePublicKeyHash const& key) + { + return m_chosenList->contains (key); + } + + // + // + //---------------------------------------------------------------------- + + private: + SourcesType m_sources; + MapType m_map; + bool m_chosenListNeedsUpdate; + ChosenList::Ptr m_chosenList; + }; + + //-------------------------------------------------------------------------- + +public: + explicit ValidatorsImp (Listener* listener) + : m_listener (listener) + , m_thread ("Validators") + , m_timer (this) + { + //m_thread.start (this); + } + + ~ValidatorsImp () + { + } + + void addSource (Source* source) + { + m_thread.call (&Logic::addSource, &m_logic, source); + } + + void addStaticSource (Source* source) + { + m_thread.call (&Logic::addStaticSource, &m_logic, source); + } + + void receiveValidation (ReceivedValidation const& rv) + { + m_thread.call (&Logic::receiveValidation, &m_logic, rv); + } + + //-------------------------------------------------------------------------- + + void onDeadlineTimer (DeadlineTimer&) + { + // This will make us fall into the idle proc as needed + // + m_thread.interrupt (); + } + + void threadInit () + { + m_timer.setRecurringExpiration (secondsPerUpdate); + } + + void threadExit () + { + } + + bool threadIdle () + { + bool interrupted = false; + + struct ThreadCancelCallback : Source::CancelCallback, Uncopyable + { + explicit ThreadCancelCallback (ThreadWithCallQueue& thread) + : m_thread (thread) + , m_interrupted (false) + { + } + + bool shouldCancel () + { + if (m_interrupted) + return true; + return m_interrupted = m_thread.interruptionPoint (); + } + + private: + ThreadWithCallQueue& m_thread; + bool m_interrupted; + }; + + ThreadCancelCallback cancelCallback (m_thread); + + m_logic.checkSources (cancelCallback); + + return interrupted; + } + +private: + Logic m_logic; + Listener* const m_listener; + ThreadWithCallQueue m_thread; + DeadlineTimer m_timer; +}; + +#endif diff --git a/modules/ripple_core/validator/ripple_StringsValidatorSource.cpp b/modules/ripple_core/validator/ripple_StringsValidatorSource.cpp deleted file mode 100644 index 96d8592066..0000000000 --- a/modules/ripple_core/validator/ripple_StringsValidatorSource.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -class StringsValidatorSourceImp : public StringsValidatorSource -{ -public: - StringsValidatorSourceImp (StringArray const& strings) - { - } - - ~StringsValidatorSourceImp () - { - } - - Array fetch () - { - return Array (); - } - -private: -}; - -StringsValidatorSource* StringsValidatorSource::New (StringArray const& strings) -{ - return new StringsValidatorSourceImp (strings); -} diff --git a/modules/ripple_core/validator/ripple_TrustedUriValidatorSource.cpp b/modules/ripple_core/validator/ripple_TrustedUriValidatorSource.cpp deleted file mode 100644 index e78fb55d1d..0000000000 --- a/modules/ripple_core/validator/ripple_TrustedUriValidatorSource.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -class TrustedUriValidatorSourceImp : public TrustedUriValidatorSource -{ -public: - explicit TrustedUriValidatorSourceImp (String const url) - : m_url (url) - { - } - - ~TrustedUriValidatorSourceImp () - { - } - - Array fetch () - { - return Array (); - } - -private: - String const m_url; -}; - -TrustedUriValidatorSource* TrustedUriValidatorSource::New (String url) -{ - return new TrustedUriValidatorSourceImp (url); -} diff --git a/modules/ripple_core/validator/ripple_ValidatorImp.h b/modules/ripple_core/validator/ripple_ValidatorImp.h deleted file mode 100644 index 14f217d022..0000000000 --- a/modules/ripple_core/validator/ripple_ValidatorImp.h +++ /dev/null @@ -1,12 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -#ifndef RIPPLE_VALIDATORLISTIMP_H_INCLUDED -#define RIPPLE_VALIDATORLISTIMP_H_INCLUDED - -// This is a private header - -#endif diff --git a/modules/ripple_core/validator/ripple_ValidatorList.h b/modules/ripple_core/validator/ripple_ValidatorList.h deleted file mode 100644 index 3b72d56dec..0000000000 --- a/modules/ripple_core/validator/ripple_ValidatorList.h +++ /dev/null @@ -1,10 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -#ifndef RIPPLE_VALIDATORLIST_H_INCLUDED -#define RIPPLE_VALIDATORLIST_H_INCLUDED - -#endif diff --git a/modules/ripple_core/validator/ripple_Validators.cpp b/modules/ripple_core/validator/ripple_Validators.cpp deleted file mode 100644 index 5fcffd3be0..0000000000 --- a/modules/ripple_core/validator/ripple_Validators.cpp +++ /dev/null @@ -1,451 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -/* - -Goal: - - Provide the listener with a ValidatorList. - - This forms the UNL - -Task: - - fetch ValidatorInfo array from a source - - - We have the old one and the new one, compute the following: - - * unchanged validators list - * new validators list - * removed validators list - - - From the unchanged / new / removed, figure out what to do. - -Two important questions: - -- Are there any validators in my ChosenValidators that I dont want - * For example, they have dropped off all the trusted lists - -- Do I have enough? - -*/ - -class ValidatorsImp - : public Validators - , private ThreadWithCallQueue::EntryPoints - , private DeadlineTimer::Listener - , LeakChecked -{ -public: - // Tunable constants - enum - { - // We will fetch a source at this interval - hoursBetweenFetches = 24 - - ,secondsBetweenFetches = hoursBetweenFetches * 60 * 60 - - // Wake up every hour to check source times - ,secondsPerUpdate = 60 * 60 - - // This tunes the preallocated arrays - ,expectedNumberOfResults = 1000 - }; - - //-------------------------------------------------------------------------- - - struct SourceInfo : LeakChecked - { - enum Status - { - statusNone, - statusFetched, - statusFailed, - }; - - explicit SourceInfo (Source* source_) - : source (source_) - , status (statusNone) - , numberOfFailures (0) - { - } - - ScopedPointer const source; - Status status; - Time whenToFetch; - int numberOfFailures; - Validator::List::Ptr list; - }; - - //-------------------------------------------------------------------------- - - // Called during the list comparison - // - struct CompareCallback - { - virtual void onValidatorAdded (Validator const& validator) { } - virtual void onValidatorRemoved (Validator const& validator) { } - virtual void onValidatorUnchanged (Validator const& validator) { } - }; - - // Given the old list and the new list for a source, this - // computes which validators were added or removed, and - // updates some statistics. - // - static void compareLists (Validator::List const& oldList, - Validator::List const& newList, - CompareCallback& callback) - { - // Validator::List is always sorted so walk both arrays and - // do an element-wise comparison to perform set calculations. - // - int i = 0; - int j = 0; - while (i < oldList.size () || j < newList.size ()) - { - if (i < oldList.size () && j < newList.size ()) - { - int const compare = Validator::Compare::compareElements ( - oldList [i], newList [j]); - - if (compare < 0) - { - callback.onValidatorRemoved (*oldList [i]); - ++i; - } - else if (compare > 0) - { - callback.onValidatorAdded (*newList [j]); - ++j; - } - else - { - bassert (oldList [i] == newList [j]); - - callback.onValidatorUnchanged (*newList [j]); - ++i; - ++j; - } - } - else if (i < oldList.size ()) - { - callback.onValidatorRemoved (*oldList [i]); - ++i; - } - else - { - bassert (j < newList.size ()); - - callback.onValidatorAdded (*newList [j]); - ++j; - } - } - } - - // Encapsulates the logic for creating the chosen validators. - // This is a separate class to facilitate the unit tests. - // - class Logic : public CompareCallback - { - private: - HashMap m_map; - - OwnedArray m_sources; - - public: - Logic () - { - } - - void addSource (Source* source) - { - m_sources.add (new SourceInfo (source)); - } - - OwnedArray & getSources () - { - return m_sources; - } - - void onValidatorAdded (Validator const& validator) - { - } - - void onValidatorRemoved (Validator const& validator) - { - } - - void onValidatorUnchanged (Validator const& validator) - { - } - - // Produces an array of references to validators given the validator info. - // - Validator::List::Ptr createListFromInfo (Array & info) - { - Validator::Info::sortAndRemoveDuplicates (info); - - SharedObjectArray items; - - items.ensureStorageAllocated (info.size ()); - - for (int i = 0; i < info.size (); ++i) - { - Validator::PublicKey const& key (info [i].publicKey); - - Validator::Ptr validator = m_map [key]; - - if (validator == nullptr) - { - validator = new Validator (key); - - //m_map.set (key, validator); - } - - items.add (validator); - } - - return new Validator::List (items); - } - - // Fetch the validators from a source and process the result - // - void fetchAndProcessSource (SourceInfo& sourceInfo) - { - Array newInfo = sourceInfo.source->fetch (); - - if (newInfo.size () != 0) - { - sourceInfo.status = SourceInfo::statusFetched; - - sourceInfo.whenToFetch = Time::getCurrentTime () + - RelativeTime (hoursBetweenFetches * 60.0 * 60.0); - - Validator::List::Ptr newList (createListFromInfo (newInfo)); - - compareLists (*sourceInfo.list, *newList, *this); - - sourceInfo.list = newList; - } - else - { - // Failed to fetch, don't update fetch time - sourceInfo.status = SourceInfo::statusFailed; - sourceInfo.numberOfFailures++; - } - } - - }; - - //-------------------------------------------------------------------------- - -public: - explicit ValidatorsImp (Validators::Listener* listener) - : m_listener (listener) - , m_thread ("Validators") - , m_timer (this) - { - m_thread.start (this); - } - - ~ValidatorsImp () - { - } - - void addSource (Source* source) - { - m_thread.call (&ValidatorsImp::doAddSource, this, source); - } - - void doAddSource (Source* source) - { - m_logic.addSource (source); - } - - void onDeadlineTimer (DeadlineTimer&) - { - // This will make us fall into the idle proc as needed - // - m_thread.interrupt (); - } - - // Fetch sources whose deadline timers have arrived. - // - bool scanSources () - { - bool interrupted = false; - - for (int i = 0; i < m_logic.getSources ().size (); ++i) - { - SourceInfo& sourceInfo (*m_logic.getSources ()[i]); - - Time const currentTime = Time::getCurrentTime (); - - if (currentTime <= sourceInfo.whenToFetch) - { - m_logic.fetchAndProcessSource (sourceInfo); - } - - interrupted = m_thread.interruptionPoint (); - - if (interrupted) - break; - } - - return interrupted; - } - - void threadInit () - { - m_timer.setRecurringExpiration (secondsPerUpdate); - } - - void threadExit () - { - } - - bool threadIdle () - { - bool interrupted = false; - - interrupted = scanSources (); - - return interrupted; - } - -private: - Logic m_logic; - Validators::Listener* const m_listener; - ThreadWithCallQueue m_thread; - DeadlineTimer m_timer; -}; - -Validators* Validators::New (Listener* listener) -{ - return new ValidatorsImp (listener); -} - -//------------------------------------------------------------------------------ - -class ValidatorsTests : public UnitTest -{ -public: - // Produces validators for unit tests. - class TestSource : public Validators::Source - { - public: - TestSource (unsigned int startIndex, unsigned int endIndex) - : m_startIndex (startIndex) - , m_endIndex (endIndex) - { - } - - Array fetch () - { - Array results; - - for (unsigned int publicKeyIndex = m_startIndex; publicKeyIndex <= m_endIndex; ++publicKeyIndex) - { - Validator::Info info; - - info.publicKey = Validator::PublicKey::createFromInteger (publicKeyIndex); - - results.add (info); - } - - return results; - } - - private: - unsigned int const m_startIndex; - unsigned int const m_endIndex; - }; - - //-------------------------------------------------------------------------- - - struct TestCompareCallback : public ValidatorsImp::CompareCallback - { - int numTotal; - int numAdded; - int numRemoved; - int numUnchanged; - - TestCompareCallback () - : numTotal (0) - , numAdded (0) - , numRemoved (0) - , numUnchanged (0) - { - } - - void onValidatorAdded (Validator const& validator) - { - ++numTotal; - ++numAdded; - } - - void onValidatorRemoved (Validator const& validator) - { - ++numTotal; - ++numRemoved; - } - - void onValidatorUnchanged (Validator const& validator) - { - ++numTotal; - ++numUnchanged; - } - }; - - //-------------------------------------------------------------------------- - - ValidatorsTests () : UnitTest ("Validators", "ripple", runManual) - { - } - - // Check logic for comparing a source's fetch results - void testCompare () - { - beginTestCase ("compare"); - - { - Array results = TestSource (1, 32).fetch (); - expect (results.size () == 32); - } - - { - Array oldInfo = TestSource (1, 4).fetch (); - expect (oldInfo.size () == 4); - - Array newInfo = TestSource (3, 6).fetch (); - expect (newInfo.size () == 4); - - ValidatorsImp::Logic logic; - - Validator::List::Ptr oldList = logic.createListFromInfo (oldInfo); - expect (oldList->size () == 4); - - Validator::List::Ptr newList = logic.createListFromInfo (newInfo); - expect (newList->size () == 4); - - TestCompareCallback cb; - ValidatorsImp::compareLists (*oldList, *newList, cb); - - expect (cb.numAdded == 2); - expect (cb.numRemoved == 2); - expect (cb.numUnchanged == 2); - } - } - - void runTest () - { - testCompare (); - } -}; - -static ValidatorsTests validatorsTests; - diff --git a/modules/ripple_core/validator/ripple_Validators.h b/modules/ripple_core/validator/ripple_Validators.h deleted file mode 100644 index dc29612f0a..0000000000 --- a/modules/ripple_core/validator/ripple_Validators.h +++ /dev/null @@ -1,69 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -#ifndef RIPPLE_VALIDATORS_H_INCLUDED -#define RIPPLE_VALIDATORS_H_INCLUDED - -/** Maintains the list of chosen validators. - - The algorithm for acquiring, building, and calculating metadata on - the list of chosen validators is critical to the health of the network. - - All operations are performed asynchronously on an internal thread. -*/ -class Validators : public Uncopyable -{ -public: - /** Provides a ValidatorList. - */ - class Source - { - public: - /** Destroy the source. - - If a fetch is active, it will be aborted before the - destructor returns. - */ - virtual ~Source () { } - - /** Fetch the validator list from this source. - - This call blocks. - */ - virtual Array fetch () =0; - }; - - //-------------------------------------------------------------------------- - - /** Receive event notifications on Validators operations. - */ - class Listener - { - public: - virtual void onValidatorsChosen (Validator::List::Ptr list) { } - }; - - //-------------------------------------------------------------------------- - - /** Create a new Validators object. - */ - static Validators* New (Listener* listener); - - /** Destroy the object. - - Any pending source fetch operations are aborted. - - There may be some listener calls made before the - destructor returns. - */ - virtual ~Validators () { } - - /** Add a source of validators. - */ - virtual void addSource (Source* source) = 0; -}; - -#endif