mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Set version to 0.17.0-rc3
This commit is contained in:
@@ -168,7 +168,7 @@
|
||||
// messages as needed, and collect legacy IP endpoint information.
|
||||
//
|
||||
#ifndef RIPPLE_USE_PEERFINDER
|
||||
#define RIPPLE_USE_PEERFINDER 1
|
||||
#define RIPPLE_USE_PEERFINDER 0
|
||||
#endif
|
||||
|
||||
// Here temporarily
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class ValidatorSourceFileImp : public ValidatorSourceFile
|
||||
{
|
||||
public:
|
||||
ValidatorSourceFileImp (File const& file)
|
||||
: m_file (file)
|
||||
{
|
||||
}
|
||||
|
||||
~ValidatorSourceFileImp ()
|
||||
{
|
||||
}
|
||||
|
||||
Result fetch (CancelCallback&)
|
||||
{
|
||||
Result result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
File m_file;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ValidatorSourceFile* ValidatorSourceFile::New (File const& file)
|
||||
{
|
||||
ScopedPointer <ValidatorSourceFile> object (
|
||||
new ValidatorSourceFileImp (file));
|
||||
|
||||
return object.release ();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_CORE_VALIDATOR_VALIDATORSOURCEFILE_H_INCLUDED
|
||||
#define RIPPLE_CORE_VALIDATOR_VALIDATORSOURCEFILE_H_INCLUDED
|
||||
|
||||
/** Provides validators from a text file.
|
||||
Typically this will come from a local configuration file.
|
||||
*/
|
||||
class ValidatorSourceFile : public Validators::Source
|
||||
{
|
||||
public:
|
||||
static ValidatorSourceFile* New (File const& path);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class ValidatorSourceStringsImp : public ValidatorSourceStrings
|
||||
{
|
||||
public:
|
||||
ValidatorSourceStringsImp (StringArray const& strings)
|
||||
: m_strings (strings)
|
||||
{
|
||||
}
|
||||
|
||||
~ValidatorSourceStringsImp ()
|
||||
{
|
||||
}
|
||||
|
||||
Result fetch (CancelCallback&)
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.list.ensureStorageAllocated (m_strings.size ());
|
||||
|
||||
for (int i = 0; i < m_strings.size (); ++i)
|
||||
{
|
||||
ValidatorsUtilities::parseResultLine (result, m_strings [i]);
|
||||
}
|
||||
|
||||
result.success = result.list.size () > 0;
|
||||
result.expirationTime = Time::getCurrentTime () + RelativeTime::hours (24);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
StringArray m_strings;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ValidatorSourceStrings* ValidatorSourceStrings::New (StringArray const& strings)
|
||||
{
|
||||
ScopedPointer <ValidatorSourceStrings> object (
|
||||
new ValidatorSourceStringsImp (strings));
|
||||
|
||||
return object.release ();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#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 ValidatorSourceStrings : public Validators::Source
|
||||
{
|
||||
public:
|
||||
static ValidatorSourceStrings* New (StringArray const& strings);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class ValidatorSourceURLImp : public ValidatorSourceURL
|
||||
{
|
||||
public:
|
||||
explicit ValidatorSourceURLImp (UniformResourceLocator const& url)
|
||||
: m_url (url)
|
||||
{
|
||||
}
|
||||
|
||||
~ValidatorSourceURLImp ()
|
||||
{
|
||||
}
|
||||
|
||||
Result fetch (CancelCallback&)
|
||||
{
|
||||
Result result;
|
||||
|
||||
ScopedPointer <HTTPClientBase> client (HTTPClientBase::New ());
|
||||
|
||||
HTTPClientBase::Result httpResult (client->get (m_url));
|
||||
|
||||
if (httpResult.error == 0)
|
||||
{
|
||||
Logger::outputDebugString (httpResult.response->toString ());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
UniformResourceLocator m_url;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ValidatorSourceURL* ValidatorSourceURL::New (
|
||||
UniformResourceLocator const& url)
|
||||
{
|
||||
ScopedPointer <ValidatorSourceURL> object (
|
||||
new ValidatorSourceURLImp (url));
|
||||
|
||||
return object.release ();
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_CORE_VALIDATOR_VALIDATORSOURCETRUSTEDURL_H_INCLUDED
|
||||
#define RIPPLE_CORE_VALIDATOR_VALIDATORSOURCETRUSTEDURL_H_INCLUDED
|
||||
|
||||
/** Provides validators from a trusted URI (e.g. HTTPS)
|
||||
*/
|
||||
class ValidatorSourceURL : public Validators::Source
|
||||
{
|
||||
public:
|
||||
static ValidatorSourceURL* New (UniformResourceLocator const& url);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,258 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
|
||||
Information to track:
|
||||
|
||||
- Percentage of validations that the validator has signed
|
||||
- Number of validations the validator signed that never got accepted
|
||||
|
||||
|
||||
- Target number for Chosen
|
||||
- Pseudo-randomly choose a subset from Chosen
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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:
|
||||
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.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Validators::Source::Result::Result ()
|
||||
: success (false)
|
||||
, message ("uninitialized")
|
||||
{
|
||||
}
|
||||
|
||||
void Validators::Source::Result::swapWith (Result& other)
|
||||
{
|
||||
std::swap (success, other.success);
|
||||
std::swap (message, other.message);
|
||||
list.swapWith (other.list);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Validators* Validators::New ()
|
||||
{
|
||||
return new ValidatorsImp (nullptr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ValidatorsTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
numberOfTestValidators = 1000
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
struct Payload
|
||||
{
|
||||
Payload ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class Config>
|
||||
class PeerLogic : public TestOverlay::PeerLogicBase <Config>
|
||||
{
|
||||
public:
|
||||
typedef TestOverlay::PeerLogicBase <Config> Base;
|
||||
typedef typename Config::Payload Payload;
|
||||
typedef typename Base::Connection Connection;
|
||||
typedef typename Base::Peer Peer;
|
||||
typedef typename Base::Message Message;
|
||||
typedef typename Config::SizeType SizeType;
|
||||
|
||||
explicit PeerLogic (Peer& peer)
|
||||
: TestOverlay::PeerLogicBase <Config> (peer)
|
||||
{
|
||||
}
|
||||
|
||||
~PeerLogic ()
|
||||
{
|
||||
}
|
||||
|
||||
void step ()
|
||||
{
|
||||
if (this->peer().id () == 1)
|
||||
{
|
||||
if (this->peer().network().steps() == 0)
|
||||
{
|
||||
this->peer().network().state().increment();
|
||||
this->peer().send_all (Payload (1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void receive (Connection const& c, Message const& m)
|
||||
{
|
||||
if (this->peer().id () != 1)
|
||||
{
|
||||
this->peer().network().state().increment();
|
||||
this->peer().send_all_if (Message (m.id(),
|
||||
m.payload().withHop ()),
|
||||
typename Connection::IsNotPeer (c.peer()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Params : TestOverlay::ConfigType <
|
||||
Params,
|
||||
TestOverlay::StateBase,
|
||||
PeerLogic
|
||||
>
|
||||
{
|
||||
typedef TestOverlay::PremadeInitPolicy <250, 3> InitPolicy;
|
||||
};
|
||||
|
||||
typedef Params::Network Network;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
struct TestSource : Validators::Source
|
||||
{
|
||||
TestSource (String const& name, uint32 start, uint32 end)
|
||||
: m_name (name)
|
||||
, m_start (start)
|
||||
, m_end (end)
|
||||
{
|
||||
}
|
||||
|
||||
Result fetch (CancelCallback& cancel)
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.success = true;
|
||||
result.message = String::empty;
|
||||
result.list.ensureStorageAllocated (numberOfTestValidators);
|
||||
|
||||
for (uint32 i = m_start ; i < m_end; ++i)
|
||||
{
|
||||
Info info;
|
||||
info.key = Validators::KeyType::createFromInteger (i);
|
||||
result.list.add (info);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String m_name;
|
||||
std::size_t m_start;
|
||||
std::size_t m_end;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void addSources (ValidatorsImp::Logic& logic)
|
||||
{
|
||||
#if 0
|
||||
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));
|
||||
#else
|
||||
logic.addSource (new TestSource ("source 1", 0, 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
struct Result
|
||||
{
|
||||
Result ();
|
||||
void swapWith (Result& other);
|
||||
|
||||
bool success;
|
||||
String message;
|
||||
Time expirationTime;
|
||||
Array <Info> list;
|
||||
};
|
||||
virtual Result 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 static source of validators from a string array. */
|
||||
/** @{ */
|
||||
virtual void addStrings (std::vector <std::string> const& strings) = 0;
|
||||
virtual void addStrings (StringArray const& stringArray) = 0;
|
||||
/** @} */
|
||||
|
||||
/** Add a static source of validators from a text file. */
|
||||
virtual void addFile (File const& file) = 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;
|
||||
|
||||
/** Add a live source of validators from a trusted URL.
|
||||
The URL will be contacted periodically to update the list.
|
||||
*/
|
||||
virtual void addURL (UniformResourceLocator const& url) = 0;
|
||||
|
||||
/** 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;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// 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
|
||||
@@ -1,485 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ValidatorsImp>
|
||||
{
|
||||
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 SharedPtr <ChosenList> Ptr;
|
||||
|
||||
struct Info
|
||||
{
|
||||
Info ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//typedef HashMap <KeyType, Info, KeyType::HashFunction> MapType;
|
||||
typedef boost::unordered_map <KeyType, Info, KeyType::HashFunction> MapType;
|
||||
|
||||
ChosenList (std::size_t expectedSize = 0)
|
||||
{
|
||||
// Available only in recent boost versions?
|
||||
//m_map.reserve (expectedSize);
|
||||
}
|
||||
|
||||
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 SourceDesc
|
||||
{
|
||||
enum
|
||||
{
|
||||
keysPreallocationSize = 1000
|
||||
};
|
||||
|
||||
enum Status
|
||||
{
|
||||
statusNone,
|
||||
statusFetched,
|
||||
statusFailed
|
||||
};
|
||||
|
||||
ScopedPointer <Source> source;
|
||||
Status status;
|
||||
Time whenToFetch;
|
||||
int numberOfFailures;
|
||||
|
||||
// The result of the last fetch
|
||||
Source::Result result;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
SourceDesc () noexcept
|
||||
: status (statusNone)
|
||||
, whenToFetch (Time::getCurrentTime ())
|
||||
, numberOfFailures (0)
|
||||
{
|
||||
}
|
||||
|
||||
~SourceDesc ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef DynamicList <SourceDesc> SourcesType;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Information associated with each distinguishable validator
|
||||
//
|
||||
struct ValidatorInfo
|
||||
{
|
||||
ValidatorInfo ()
|
||||
: refCount (0)
|
||||
{
|
||||
}
|
||||
|
||||
int refCount;
|
||||
};
|
||||
|
||||
//typedef HashMap <KeyType, ValidatorInfo, KeyType::HashFunction> MapType;
|
||||
typedef boost::unordered_map <KeyType, ValidatorInfo, KeyType::HashFunction> MapType;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
Logic ()
|
||||
: m_chosenListNeedsUpdate (false)
|
||||
{
|
||||
}
|
||||
|
||||
// Add a one-time static source.
|
||||
// Fetch is called right away, this call blocks.
|
||||
//
|
||||
void addStaticSource (Source* source)
|
||||
{
|
||||
ScopedPointer <Source> object (source);
|
||||
|
||||
NoOpCancelCallback cancelCallback;
|
||||
|
||||
Source::Result result (object->fetch (cancelCallback));
|
||||
|
||||
if (result.success)
|
||||
{
|
||||
addSourceInfo (result.list);
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO NOTE Maybe log the error and message?
|
||||
}
|
||||
}
|
||||
|
||||
// Add a live source to the list of sources.
|
||||
//
|
||||
void addSource (Source* source)
|
||||
{
|
||||
SourceDesc& desc (*m_sources.emplace_back ());
|
||||
desc.source = source;
|
||||
}
|
||||
|
||||
// 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 <Source::Info> const& list)
|
||||
{
|
||||
for (std::size_t i = 0; i < list.size (); ++i)
|
||||
{
|
||||
Source::Info const& info (list.getReference (i));
|
||||
std::pair <MapType::iterator, bool> result (
|
||||
m_map.emplace (info.key, ValidatorInfo ()));
|
||||
ValidatorInfo& validatorInfo (result.first->second);
|
||||
++validatorInfo.refCount;
|
||||
if (result.second)
|
||||
{
|
||||
// This is a new one
|
||||
markDirtyChosenList ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decrement the reference count of each item in the list
|
||||
// in the map
|
||||
//
|
||||
void removeSourceInfo (Array <Source::Info> 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->second);
|
||||
if (--validatorInfo.refCount == 0)
|
||||
{
|
||||
// Last reference removed
|
||||
m_map.erase (iter);
|
||||
markDirtyChosenList ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch one source
|
||||
//
|
||||
void fetchSource (SourceDesc& desc, Source::CancelCallback& callback)
|
||||
{
|
||||
Source::Result result (desc.source->fetch (callback));
|
||||
|
||||
if (! callback.shouldCancel ())
|
||||
{
|
||||
// Reset fetch timer for the source.
|
||||
desc.whenToFetch = Time::getCurrentTime () +
|
||||
RelativeTime (secondsBetweenFetches);
|
||||
|
||||
if (result.success)
|
||||
{
|
||||
// Add the new source info to the map
|
||||
addSourceInfo (result.list);
|
||||
|
||||
// Swap lists
|
||||
desc.result.swapWith (result);
|
||||
|
||||
// Remove the old source info from the map
|
||||
removeSourceInfo (result.list);
|
||||
|
||||
// See if we need to rebuild
|
||||
checkDirtyChosenList ();
|
||||
|
||||
// Reset failure status
|
||||
desc.numberOfFailures = 0;
|
||||
desc.status = SourceDesc::statusFetched;
|
||||
}
|
||||
else
|
||||
{
|
||||
++desc.numberOfFailures;
|
||||
desc.status = SourceDesc::statusFailed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
SourceDesc& desc (*iter);
|
||||
if (desc.whenToFetch <= currentTime)
|
||||
fetchSource (desc, 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 (m_map.size ()));
|
||||
|
||||
for (MapType::iterator iter = m_map.begin ();
|
||||
iter != m_map.end (); ++iter)
|
||||
{
|
||||
ChosenList::Info info;
|
||||
list->insert (iter->first, 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 addStrings (std::vector <std::string> const& strings)
|
||||
{
|
||||
StringArray stringArray;
|
||||
stringArray.ensureStorageAllocated (strings.size());
|
||||
for (std::size_t i = 0; i < strings.size(); ++i)
|
||||
stringArray.add (strings [i]);
|
||||
addStrings (stringArray);
|
||||
}
|
||||
|
||||
void addStrings (StringArray const& stringArray)
|
||||
{
|
||||
addStaticSource (
|
||||
ValidatorSourceStrings::New (stringArray));
|
||||
}
|
||||
|
||||
void addFile (File const& file)
|
||||
{
|
||||
addStaticSource (ValidatorSourceFile::New (file));
|
||||
}
|
||||
|
||||
void addURL (UniformResourceLocator const& url)
|
||||
{
|
||||
addSource (ValidatorSourceURL::New (url));
|
||||
}
|
||||
|
||||
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
|
||||
@@ -1,30 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
bool ValidatorsUtilities::parseInfoLine (Validators::Source::Info& info, String line)
|
||||
{
|
||||
bool success (false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void ValidatorsUtilities::parseResultLine (
|
||||
Validators::Source::Result& result,
|
||||
String line)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (! success)
|
||||
{
|
||||
Validators::Source::Info info;
|
||||
|
||||
success = parseInfoLine (info, line);
|
||||
if (success)
|
||||
result.list.add (info);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_CORE_VALIDATORSUTILITIES_H_INCLUDED
|
||||
#define RIPPLE_CORE_VALIDATORSUTILITIES_H_INCLUDED
|
||||
|
||||
/** Common code for Validators classes.
|
||||
*/
|
||||
class ValidatorsUtilities
|
||||
{
|
||||
public:
|
||||
typedef std::vector <std::string> Strings;
|
||||
|
||||
#if 0
|
||||
/** Parse a ConstBufferSequence of newline delimited text into strings.
|
||||
This works incrementally.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
static void parseLines (Strings& lines, ConstBufferSequence const& buffers)
|
||||
{
|
||||
for (typename ConstBufferSequence::const_iterator iter = buffers.begin ();
|
||||
iter != buffers.end (); ++iter)
|
||||
parserLines (lines, *iter);
|
||||
}
|
||||
|
||||
/** Turn a linear buffer of newline delimited text into strings.
|
||||
This can be called incrementally, i.e. successive calls with
|
||||
multiple buffer segments.
|
||||
*/
|
||||
static void parseLines (Strings& lines, char const* buf, std::size_t bytes);
|
||||
#endif
|
||||
|
||||
/** Parse a string into the Source::Result.
|
||||
Invalid or comment lines will be skipped.
|
||||
Lines containing validator info will be added to the Result object.
|
||||
Metadata lines will update the corresponding Result fields.
|
||||
*/
|
||||
static void parseResultLine (
|
||||
Validators::Source::Result& result,
|
||||
String line);
|
||||
|
||||
private:
|
||||
/** Parse a string into a Source::Info.
|
||||
@return `true` on success.
|
||||
*/
|
||||
static bool parseInfoLine (Validators::Source::Info& info, String line);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -25,7 +25,7 @@ char const* BuildInfo::getRawVersionString ()
|
||||
//
|
||||
// The build version number (edit this for each release)
|
||||
//
|
||||
"0.17.0-rc2"
|
||||
"0.17.0-rc3"
|
||||
//
|
||||
// Must follow the format described here:
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user