Refactor consensus:

Classes implementing the consensus process on Ripple are cleaned
up in preparation for modularizations and compartmentalization.

Functions and state related to inter-round consensus are moved out
of NetworkOPs and into Consensus, where they are more effectively
isolated.

Some member functions are changed to free functions and some free
functions have their scope reduced to specific translation units.

* Track inter-round consensus state using new Consensus object
* Devirtualize interfaces
* Reduce NetworkOPs, Consensus and LedgerConsensus interfaces
* Add comments
This commit is contained in:
Nik Bougalis
2015-05-31 13:23:33 -07:00
parent 9111ad1a9d
commit 1a843fb4f6
20 changed files with 2748 additions and 2507 deletions

View File

@@ -1357,12 +1357,20 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\BookListeners.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\Consensus.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\ConsensusTransSetSF.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\ConsensusTransSetSF.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -1383,10 +1391,12 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\LedgerCleaner.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerConsensus.cpp">
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerConsensusImp.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\LedgerConsensusImp.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerFees.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>

View File

@@ -2097,12 +2097,21 @@
<ClInclude Include="..\..\src\ripple\app\ledger\BookListeners.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\Consensus.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\ConsensusTransSetSF.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\ConsensusTransSetSF.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.h">
<Filter>ripple\app\ledger\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
@@ -2121,9 +2130,12 @@
<ClInclude Include="..\..\src\ripple\app\ledger\impl\LedgerCleaner.h">
<Filter>ripple\app\ledger\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerConsensus.cpp">
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerConsensusImp.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\LedgerConsensusImp.h">
<Filter>ripple\app\ledger\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerFees.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>

View File

@@ -41,9 +41,9 @@ void BookListeners::publish (Json::Value const& jvObj)
std::string sObj = to_string (jvObj);
ScopedLockType sl (mLock);
NetworkOPs::SubMapType::const_iterator it = mListeners.begin ();
auto it = mListeners.cbegin ();
while (it != mListeners.end ())
while (it != mListeners.cend ())
{
InfoSub::pointer p = it->second.lock ();

View File

@@ -0,0 +1,89 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_APP_LEDGER_CONSENSUS_H_INCLUDED
#define RIPPLE_APP_LEDGER_CONSENSUS_H_INCLUDED
#include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/tx/InboundTransactions.h>
#include <ripple/app/tx/LocalTxs.h>
#include <beast/cxx14/memory.h> // <memory>
namespace ripple {
/** Implements the consensus process and provides inter-round state. */
class Consensus
{
public:
using Proposals = hash_map <NodeID, std::deque<LedgerProposal::pointer>>;
virtual
~Consensus () = default;
/** Returns whether we are issuing proposals currently. */
virtual
bool
isProposing () const = 0;
/** Returns whether we are issuing validations currently. */
virtual
bool
isValidating () const = 0;
/** Returns the number of unique proposers we observed for the LCL. */
virtual
int
getLastCloseProposers () const = 0;
/** Returns the time (in milliseconds) that the last close took. */
virtual
int
getLastCloseDuration () const = 0;
/** Called when a new round of consensus is about to begin */
virtual
std::shared_ptr<LedgerConsensus>
startRound (
InboundTransactions& inboundTransactions,
LocalTxs& localtx,
LedgerMaster& ledgerMaster,
LedgerHash const &prevLCLHash,
Ledger::ref previousLedger,
std::uint32_t closeTime) = 0;
/** Specified the network time when the last ledger closed */
virtual
void
setLastCloseTime (std::uint32_t t) = 0;
virtual
void
storeProposal (
LedgerProposal::ref proposal,
RippleAddress const& peerPublic) = 0;
};
std::unique_ptr<Consensus>
make_Consensus ();
}
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef RIPPLE_APP_CONSENSUS_LEDGERCONSENSUS_H_INCLUDED
#define RIPPLE_APP_CONSENSUS_LEDGERCONSENSUS_H_INCLUDED
#ifndef RIPPLE_APP_LEDGER_LEDGERCONSENSUS_H_INCLUDED
#define RIPPLE_APP_LEDGER_LEDGERCONSENSUS_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/LedgerProposal.h>
@@ -41,7 +41,7 @@ namespace ripple {
class LedgerConsensus
{
public:
virtual ~LedgerConsensus() = 0;
virtual ~LedgerConsensus() = default;
virtual Json::Value getJson (bool full) = 0;
@@ -66,17 +66,25 @@ public:
virtual void simulate () = 0;
};
std::shared_ptr <LedgerConsensus>
make_LedgerConsensus (
int previousProposers, int previousConvergeTime,
InboundTransactions& inboundTransactions, LocalTxs& localtx,
LedgerHash const & prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote);
//------------------------------------------------------------------------------
/** Apply a set of transactions to a ledger
@param set The set of transactions to apply
@param applyLedger The ledger to which the transactions should
be applied.
@param checkLedger A reference ledger for determining error
messages (typically new last closed
ledger).
@param retriableTransactions collect failed transactions in this set
@param openLgr true if applyLedger is open, else false.
*/
void
applyTransactions(SHAMap const* set, Ledger::ref applyLedger,
Ledger::ref checkLedger,
CanonicalTXSet& retriableTransactions, bool openLgr);
applyTransactions(
SHAMap const* set,
Ledger::ref applyLedger,
Ledger::ref checkLedger,
CanonicalTXSet& retriableTransactions,
bool openLgr);
} // ripple

View File

@@ -120,7 +120,6 @@ public:
virtual void addHeldTransaction (Transaction::ref trans) = 0;
virtual void fixMismatch (Ledger::ref ledger) = 0;
virtual bool haveLedgerRange (std::uint32_t from, std::uint32_t to) = 0;
virtual bool haveLedger (std::uint32_t seq) = 0;
virtual void clearLedger (std::uint32_t seq) = 0;
virtual bool getValidatedRange (std::uint32_t& minVal, std::uint32_t& maxVal) = 0;

View File

@@ -24,57 +24,6 @@
namespace ripple {
/** Determines whether the current ledger should close at this time.
This function should be called when a ledger is open and there is no close
in progress, or when a transaction is received and no close is in progress.
@param anyTransactions indicates whether any transactions have been received
@param previousProposers proposers in the last closing
@param proposersClosed proposers who have currently closed this ledger
@param proposersValidated proposers who have validated the last closed ledger
@param previousMSeconds time, in milliseconds, for the previous ledger to
reach consensus (in milliseconds)
@param currentMSeconds time, in milliseconds since the previous ledger closed
@param openMSeconds time, in milliseconds, since the previous LCL was computed
@param idleInterval the network's desired idle interval
*/
bool shouldCloseLedger (
bool anyTransactions,
int previousProposers,
int proposersClosed,
int proposersValidated,
int previousMSeconds,
int currentMSeconds,
int openMSeconds,
int idleInterval);
/** What state the consensus process is on. */
enum class ConsensusState
{
No, // We do not have consensus
MovedOn, // The network has consensus without us
Yes // We have consensus along with the network
};
/** Determine whether the network reached consensus and whether we joined.
@param previousProposers proposers in the last closing (not including us)
@param currentProposers proposers in this closing so far (not including us)
@param currentAgree proposers who agree with us
@param currentFinished proposers who have validated a ledger after this one
@param previousAgreeTime how long, in milliseconds, it took to agree on the
last ledger
@param currentAgreeTime how long, in milliseconds, we've been trying to agree
*/
ConsensusState checkConsensus (
int previousProposers,
int currentProposers,
int currentAgree,
int currentClosed,
int previousAgreeTime,
int currentAgreeTime);
/** Calculates the close time resolution for the specified ledger.
The Ripple protocol uses binning to represent time intervals using only one

View File

@@ -0,0 +1,181 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerTiming.h>
#include <ripple/app/ledger/impl/ConsensusImp.h>
#include <ripple/app/ledger/impl/LedgerConsensusImp.h>
#include <ripple/basics/Log.h>
#include <beast/utility/Journal.h>
namespace ripple {
ConsensusImp::ConsensusImp ()
: journal_ (deprecatedLogs().journal("Consensus"))
, feeVote_ (make_FeeVote (setup_FeeVote (getConfig().section ("voting")),
deprecatedLogs().journal("FeeVote")))
, proposing_ (false)
, validating_ (false)
, lastCloseProposers_ (0)
, lastCloseConvergeTook_ (1000 * LEDGER_IDLE_INTERVAL)
, lastValidationTimestamp_ (0)
, lastCloseTime_ (0)
{
}
bool
ConsensusImp::isProposing () const
{
return proposing_;
}
bool
ConsensusImp::isValidating () const
{
return validating_;
}
int
ConsensusImp::getLastCloseProposers () const
{
return lastCloseProposers_;
}
int
ConsensusImp::getLastCloseDuration () const
{
return lastCloseConvergeTook_;
}
std::shared_ptr<LedgerConsensus>
ConsensusImp::startRound (
InboundTransactions& inboundTransactions,
LocalTxs& localtx,
LedgerMaster& ledgerMaster,
LedgerHash const &prevLCLHash,
Ledger::ref previousLedger,
std::uint32_t closeTime)
{
return make_LedgerConsensus (*this, lastCloseProposers_,
lastCloseConvergeTook_, inboundTransactions, localtx, ledgerMaster,
prevLCLHash, previousLedger, closeTime, *feeVote_);
}
void
ConsensusImp::setProposing (bool p, bool v)
{
proposing_ = p;
validating_ = v;
}
STValidation::ref
ConsensusImp::getLastValidation () const
{
return lastValidation_;
}
void
ConsensusImp::setLastValidation (STValidation::ref v)
{
lastValidation_ = v;
}
void
ConsensusImp::newLCL (
int proposers,
int convergeTime,
uint256 const& ledgerHash)
{
lastCloseProposers_ = proposers;
lastCloseConvergeTook_ = convergeTime;
lastCloseHash_ = ledgerHash;
}
std::uint32_t
ConsensusImp::validationTimestamp (std::uint32_t vt)
{
if (vt <= lastValidationTimestamp_)
vt = lastValidationTimestamp_ + 1;
lastValidationTimestamp_ = vt;
return vt;
}
std::uint32_t
ConsensusImp::getLastCloseTime () const
{
return lastCloseTime_;
}
void
ConsensusImp::setLastCloseTime (std::uint32_t t)
{
lastCloseTime_ = t;
}
void
ConsensusImp::storeProposal (
LedgerProposal::ref proposal,
RippleAddress const& peerPublic)
{
auto& props = storedProposals_[peerPublic.getNodeID ()];
if (props.size () >= (unsigned) (getLastCloseProposers () + 10))
props.pop_front ();
props.push_back (proposal);
}
// Must be called while holding the master lock
void
ConsensusImp::takePosition (int seq, std::shared_ptr<SHAMap> const& position)
{
recentPositions_[position->getHash ()] = std::make_pair (seq, position);
if (recentPositions_.size () > 4)
{
for (auto i = recentPositions_.begin (); i != recentPositions_.end ();)
{
if (i->second.first < (seq - 2))
{
recentPositions_.erase (i);
return;
}
++i;
}
}
}
Consensus::Proposals&
ConsensusImp::peekStoredProposals ()
{
return storedProposals_;
}
//==============================================================================
std::unique_ptr<Consensus>
make_Consensus ()
{
return std::make_unique<ConsensusImp> ();
}
}

View File

@@ -0,0 +1,131 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_APP_LEDGER_IMPL_CONSENSUSIMP_H_INCLUDED
#define RIPPLE_APP_LEDGER_IMPL_CONSENSUSIMP_H_INCLUDED
#include <BeastConfig.h>
#include <ripple/app/ledger/Consensus.h>
#include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/shamap/SHAMap.h>
#include <beast/utility/Journal.h>
namespace ripple {
/** Implements the consensus process and provides inter-round state. */
class ConsensusImp
: public Consensus
{
public:
ConsensusImp ();
~ConsensusImp () = default;
bool
isProposing () const override;
bool
isValidating () const override;
int
getLastCloseProposers () const override;
int
getLastCloseDuration () const override;
std::shared_ptr<LedgerConsensus>
startRound (
InboundTransactions& inboundTransactions,
LocalTxs& localtx,
LedgerMaster& ledgerMaster,
LedgerHash const &prevLCLHash,
Ledger::ref previousLedger,
std::uint32_t closeTime) override;
void
setLastCloseTime (std::uint32_t t) override;
void
storeProposal (
LedgerProposal::ref proposal,
RippleAddress const& peerPublic) override;
void
setProposing (bool p, bool v);
STValidation::ref
getLastValidation () const;
void
setLastValidation (STValidation::ref v);
void
newLCL (
int proposers,
int convergeTime,
uint256 const& ledgerHash);
std::uint32_t
validationTimestamp (std::uint32_t vt);
std::uint32_t
getLastCloseTime () const;
void takePosition (int seq, std::shared_ptr<SHAMap> const& position);
Consensus::Proposals&
peekStoredProposals ();
private:
beast::Journal journal_;
std::unique_ptr <FeeVote> feeVote_;
bool proposing_;
bool validating_;
// A pointer to the last validation that we issued
STValidation::pointer lastValidation_;
// The number of proposers who participated in the last ledger close
int lastCloseProposers_;
// How long the last ledger close took, in milliseconds
int lastCloseConvergeTook_;
// The hash of the last closed ledger
uint256 lastCloseHash_;
// The timestamp of the last validation we used, in network time. This is
// only used for our own validations.
std::uint32_t lastValidationTimestamp_;
// The last close time
std::uint32_t lastCloseTime_;
// Recent positions taken
std::map<uint256, std::pair<int, std::shared_ptr<SHAMap>>> recentPositions_;
Consensus::Proposals storedProposals_;
};
}
#endif

View File

@@ -38,8 +38,6 @@ namespace ripple {
class DisputedTx
{
public:
using pointer = std::shared_ptr <DisputedTx>;
// VFALCO `Blob` is a poor choice of parameter
DisputedTx (uint256 const& txID,
Blob const& tx, bool ourVote)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,351 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_APP_LEDGER_IMPL_LEDGERCONSENSUSIMP_H_INCLUDED
#define RIPPLE_APP_LEDGER_IMPL_LEDGERCONSENSUSIMP_H_INCLUDED
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/impl/ConsensusImp.h>
#include <ripple/app/ledger/impl/DisputedTx.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/protocol/UintTypes.h>
namespace ripple {
/**
Provides the implementation for LedgerConsensus.
Achieves consensus on the next ledger.
This object is created when the consensus process starts, and
is destroyed when the process is complete.
Nearly everything herein is invoked with the master lock.
Two things need consensus:
1. The set of transactions.
2. The close time for the ledger.
*/
class LedgerConsensusImp
: public LedgerConsensus
, public std::enable_shared_from_this <LedgerConsensusImp>
, public CountedObject <LedgerConsensusImp>
{
private:
enum class State
{
// We haven't closed our ledger yet, but others might have
open,
// Establishing consensus
establish,
// We have closed on a transaction set
finished,
// We have accepted / validated a new last closed ledger
accepted,
};
public:
/**
* The result of applying a transaction to a ledger.
*/
enum {resultSuccess, resultFail, resultRetry};
static char const* getCountedObjectName () { return "LedgerConsensus"; }
LedgerConsensusImp(LedgerConsensusImp const&) = delete;
LedgerConsensusImp& operator=(LedgerConsensusImp const&) = delete;
~LedgerConsensusImp () = default;
/**
@param previousProposers the number of participants in the last round
@param previousConvergeTime how long the last round took (ms)
@param inboundTransactions
@param localtx transactions issued by local clients
@param inboundTransactions the set of
@param localtx A set of local transactions to apply
@param prevLCLHash The hash of the Last Closed Ledger (LCL).
@param previousLedger Best guess of what the LCL was.
@param closeTime Closing time point of the LCL.
@param feeVote Our desired fee levels and voting logic.
*/
LedgerConsensusImp (
ConsensusImp& consensus,
int previousProposers,
int previousConvergeTime,
InboundTransactions& inboundTransactions,
LocalTxs& localtx,
LedgerMaster& ledgerMaster,
LedgerHash const & prevLCLHash,
Ledger::ref previousLedger,
std::uint32_t closeTime,
FeeVote& feeVote);
/**
Get the Json state of the consensus process.
Called by the consensus_info RPC.
@param full True if verbose response desired.
@return The Json state.
*/
Json::Value getJson (bool full) override;
/* The hash of the last closed ledger */
uint256 getLCL () override;
/**
We have a complete transaction set, typically acquired from the network
@param hash hash of the transaction set.
@param map the transaction set.
@param acquired true if we have acquired the transaction set.
*/
void mapComplete (
uint256 const& hash,
std::shared_ptr<SHAMap> const& map,
bool acquired) override;
/**
Check if our last closed ledger matches the network's.
This tells us if we are still in sync with the network.
This also helps us if we enter the consensus round with
the wrong ledger, to leave it with the correct ledger so
that we can participate in the next round.
*/
void checkLCL ();
/**
Change our view of the last closed ledger
@param lclHash Hash of the last closed ledger.
*/
void handleLCL (uint256 const& lclHash);
/**
On timer call the correct handler for each state.
*/
void timerEntry () override;
/**
Handle pre-close state.
*/
void statePreClose ();
/** We are establishing a consensus
Update our position only on the timer, and in this state.
If we have consensus, move to the finish state
*/
void stateEstablish ();
void stateFinished ();
void stateAccepted ();
/** Check if we've reached consensus */
bool haveConsensus ();
std::shared_ptr<SHAMap> getTransactionTree (uint256 const& hash);
/**
A server has taken a new position, adjust our tracking
Called when a peer takes a new postion.
@param newPosition the new position
@return true if we should do delayed relay of this position.
*/
bool peerPosition (LedgerProposal::ref newPosition) override;
void simulate () override;
private:
/**
We have a complete transaction set, typically acquired from the network
@param hash hash of the transaction set.
@param map the transaction set.
@param acquired true if we have acquired the transaction set.
*/
void mapCompleteInternal (
uint256 const& hash,
std::shared_ptr<SHAMap> const& map,
bool acquired);
/** We have a new last closed ledger, process it. Final accept logic
@param set Our consensus set
*/
void accept (std::shared_ptr<SHAMap> set);
/**
Compare two proposed transaction sets and create disputed
transctions structures for any mismatches
@param m1 One transaction set
@param m2 The other transaction set
*/
void createDisputes (std::shared_ptr<SHAMap> const& m1,
std::shared_ptr<SHAMap> const& m2);
/**
Add a disputed transaction (one that at least one node wants
in the consensus set and at least one node does not) to our tracking
@param txID The ID of the disputed transaction
@param tx The data of the disputed transaction
*/
void addDisputedTransaction (uint256 const& txID, Blob const& tx);
/**
Adjust the votes on all disputed transactions based
on the set of peers taking this position
@param map A disputed position
@param peers peers which are taking the position map
*/
void adjustCount (std::shared_ptr<SHAMap> const& map,
const std::vector<NodeID>& peers);
/**
Revoke our outstanding proposal, if any, and
cease proposing at least until this round ends
*/
void leaveConsensus ();
/** Make and send a proposal
*/
void propose ();
/** Let peers know that we a particular transactions set so they
can fetch it from us.
@param hash The ID of the transaction.
@param direct true if we have this transaction set locally, else a
directly connected peer has it.
*/
void sendHaveTxSet (uint256 const& hash, bool direct);
/** Send a node status change message to our directly connected peers
@param event The event which caused the status change. This is
typically neACCEPTED_LEDGER or neCLOSING_LEDGER.
@param ledger The ledger associated with the event.
*/
void statusChange (protocol::NodeEvent event, Ledger& ledger);
/** Take an initial position on what we think the consensus should be
based on the transactions that made it into our open ledger
@param initialLedger The ledger that contains our initial position.
*/
void takeInitialPosition (Ledger& initialLedger);
/**
Called while trying to avalanche towards consensus.
Adjusts our positions to try to agree with other validators.
*/
void updateOurPositions ();
/** If we radically changed our consensus context for some reason,
we need to replay recent proposals so that they're not lost.
*/
void playbackProposals ();
/** We have just decided to close the ledger. Start the consensus timer,
stash the close time, inform peers, and take a position
*/
void closeLedger ();
/**
If we missed a consensus round, we may be missing a validation.
This will send an older owed validation if we previously missed it.
*/
void checkOurValidation ();
/** We have a new LCL and must accept it */
void beginAccept (bool synchronous);
void endConsensus ();
/** Add our load fee to our validation */
void addLoad(STValidation::ref val);
private:
ConsensusImp& consensus_;
InboundTransactions& inboundTransactions_;
LocalTxs& m_localTX;
LedgerMaster& ledgerMaster_;
FeeVote& m_feeVote;
State state_;
std::uint32_t mCloseTime; // The wall time this ledger closed
uint256 mPrevLedgerHash, mNewLedgerHash, mAcquiringLedger;
Ledger::pointer mPreviousLedger;
LedgerProposal::pointer mOurPosition;
RippleAddress mValPublic, mValPrivate;
bool mProposing, mValidating, mHaveCorrectLCL, mConsensusFail;
int mCurrentMSeconds;
// How long the close has taken, expressed as a percentage of the time that
// we expected it to take.
int mClosePercent;
int mCloseResolution;
bool mHaveCloseTimeConsensus;
std::chrono::steady_clock::time_point mConsensusStartTime;
int mPreviousProposers;
// The time it took for the last consensus process to converge
int mPreviousMSeconds;
// Convergence tracking, trusted peers indexed by hash of public key
hash_map<NodeID, LedgerProposal::pointer> mPeerPositions;
// Transaction Sets, indexed by hash of transaction tree
hash_map<uint256, std::shared_ptr<SHAMap>> mAcquired;
// Disputed transactions
hash_map<uint256, std::shared_ptr <DisputedTx>> mDisputes;
hash_set<uint256> mCompares;
// Close time estimates
std::map<std::uint32_t, int> mCloseTimes;
// nodes that have bowed out of this consensus process
hash_set<NodeID> mDeadNodes;
};
//------------------------------------------------------------------------------
std::shared_ptr <LedgerConsensus>
make_LedgerConsensus (ConsensusImp& consensus, int previousProposers,
int previousConvergeTime, InboundTransactions& inboundTransactions,
LocalTxs& localtx, LedgerMaster& ledgerMaster, LedgerHash const &prevLCLHash,
Ledger::ref previousLedger, std::uint32_t closeTime, FeeVote& feeVote);
} // ripple
#endif

View File

@@ -397,13 +397,6 @@ public:
mBuildingLedgerSeq.store (i);
}
bool haveLedgerRange (std::uint32_t from, std::uint32_t to)
{
ScopedLockType sl (mCompleteLock);
std::uint32_t prevMissing = mCompleteLedgers.prevMissing (to + 1);
return (prevMissing == RangeSet::absent) || (prevMissing < from);
}
bool haveLedger (std::uint32_t seq)
{
ScopedLockType sl (mCompleteLock);

View File

@@ -25,125 +25,6 @@
namespace ripple {
bool shouldCloseLedger (
bool anyTransactions,
int previousProposers,
int proposersClosed,
int proposersValidated,
int previousMSeconds,
int currentMSeconds,
int openMSeconds,
int idleInterval)
{
if ((previousMSeconds < -1000) || (previousMSeconds > 600000) ||
(currentMSeconds < -1000) || (currentMSeconds > 600000))
{
WriteLog (lsWARNING, LedgerTiming) <<
"shouldCloseLedger Trans=" << (anyTransactions ? "yes" : "no") <<
" Prop: " << previousProposers << "/" << proposersClosed <<
" Secs: " << currentMSeconds << " (last: " << previousMSeconds << ")";
return true;
}
if (!anyTransactions)
{
// did we miss a transaction?
if (proposersClosed > (previousProposers / 4))
{
WriteLog (lsTRACE, LedgerTiming) <<
"no transactions, many proposers: now (" << proposersClosed <<
" closed, " << previousProposers << " before)";
return true;
}
// Only close if we have idled for too long.
return currentMSeconds >= (idleInterval * 1000); // normal idle
}
// If we have any transactions, we don't want to close too frequently:
if (openMSeconds < LEDGER_MIN_CLOSE)
{
if ((proposersClosed + proposersValidated) < (previousProposers / 2 ))
{
WriteLog (lsDEBUG, LedgerTiming) <<
"Must wait minimum time before closing";
return false;
}
}
if (currentMSeconds < previousMSeconds)
{
if ((proposersClosed + proposersValidated) < previousProposers)
{
WriteLog (lsDEBUG, LedgerTiming) <<
"We are waiting for more closes/validations";
return false;
}
}
return true;
}
bool
checkConsensusReached (int agreeing, int proposing)
{
int currentPercentage = (agreeing * 100) / (proposing + 1);
return currentPercentage > minimumConsensusPercentage;
}
ConsensusState checkConsensus (
int previousProposers,
int currentProposers,
int currentAgree,
int currentFinished,
int previousAgreeTime,
int currentAgreeTime)
{
WriteLog (lsTRACE, LedgerTiming) <<
"checkConsensus: prop=" << currentProposers <<
"/" << previousProposers <<
" agree=" << currentAgree << " validated=" << currentFinished <<
" time=" << currentAgreeTime << "/" << previousAgreeTime;
if (currentAgreeTime <= LEDGER_MIN_CONSENSUS)
return ConsensusState::No;
if (currentProposers < (previousProposers * 3 / 4))
{
// Less than 3/4 of the last ledger's proposers are present; don't
// rush: we may need more time.
if (currentAgreeTime < (previousAgreeTime + LEDGER_MIN_CONSENSUS))
{
WriteLog (lsTRACE, LedgerTiming) <<
"too fast, not enough proposers";
return ConsensusState::No;
}
}
// Have we, together with the nodes on our UNL list, reached the treshold
// to declare consensus?
if (checkConsensusReached (currentAgree + 1, currentProposers))
{
WriteLog (lsDEBUG, LedgerTiming) << "normal consensus";
return ConsensusState::Yes;
}
// Have sufficient nodes on our UNL list moved on and reached the threshold
// to declare consensus?
if (checkConsensusReached (currentFinished, currentProposers))
{
WriteLog (lsWARNING, LedgerTiming) <<
"We see no consensus, but 80% of nodes have moved on";
return ConsensusState::MovedOn;
}
// no consensus yet
WriteLog (lsTRACE, LedgerTiming) << "no consensus";
return ConsensusState::No;
}
int getNextLedgerTimeResolution (
int previousResolution,
bool previousAgree,

View File

@@ -19,10 +19,10 @@
#include <BeastConfig.h>
#include <ripple/protocol/Quality.h>
#include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/app/ledger/Consensus.h>
#include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/ledger/AcceptedLedger.h>
#include <ripple/ledger/CachedView.h>
#include <ripple/app/ledger/InboundLedger.h>
@@ -38,6 +38,7 @@
#include <ripple/app/misc/Validations.h>
#include <ripple/app/misc/impl/AccountTxPaging.h>
#include <ripple/app/misc/UniqueNodeList.h>
#include <ripple/app/tx/TransactionEngine.h>
#include <ripple/app/tx/TransactionMaster.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/Time.h>
@@ -119,22 +120,15 @@ public:
: NetworkOPs (parent)
, m_clock (clock)
, m_journal (journal)
, m_localTX (LocalTxs::New ())
, m_feeVote (make_FeeVote (setup_FeeVote (getConfig().section ("voting")),
deprecatedLogs().journal("FeeVote")))
, m_localTX (make_LocalTxs ())
, mMode (omDISCONNECTED)
, mNeedNetworkLedger (false)
, mProposing (false)
, mValidating (false)
, m_amendmentBlocked (false)
, m_heartbeatTimer (this)
, m_clusterTimer (this)
, mConsensus (make_Consensus ())
, m_ledgerMaster (ledgerMaster)
, mCloseTimeOffset (0)
, lastCloseProposers_ (0)
, lastCloseConvergeTook_ (1000 * LEDGER_IDLE_INTERVAL)
, mLastCloseTime (0)
, mLastValidationTime (0)
, mFetchPack ("FetchPack", 65536, 45, clock,
deprecatedLogs().journal("TaggedCache"))
, mFetchSeq (0)
@@ -157,14 +151,14 @@ public:
private:
std::uint32_t getCloseTimeNC (int& offset) const;
bool isValidated (std::uint32_t seq, uint256 const& hash) /*override*/;
public:
// Use *only* to timestamp our own validation.
std::uint32_t getValidationTimeNC () override;
void closeTimeOffset (int) override;
/** On return the offset param holds the System time offset in seconds.
*/
boost::posix_time::ptime getNetworkTimePT(int& offset) const override;
boost::posix_time::ptime getNetworkTimePT(int& offset) const;
std::uint32_t getLedgerID (uint256 const& hash) override;
std::uint32_t getCurrentLedgerID () override;
OperatingMode getOperatingMode () const override
@@ -181,10 +175,6 @@ public:
{
return m_ledgerMaster.getValidatedLedger ();
}
Ledger::pointer getPublishedLedger () override
{
return m_ledgerMaster.getPublishedLedger ();
}
Ledger::pointer getCurrentLedger () override
{
return m_ledgerMaster.getCurrentLedger ();
@@ -202,11 +192,9 @@ public:
}
// Do we have this inclusive range of ledgers in our database
bool haveLedgerRange (std::uint32_t from, std::uint32_t to) override;
bool haveLedger (std::uint32_t seq) override;
std::uint32_t getValidatedSeq () override;
bool isValidated (std::uint32_t seq) override;
bool isValidated (std::uint32_t seq, uint256 const& hash) override;
bool isValidated (Ledger::ref l) override
{
return isValidated (l->getLedgerSeq (), l->getHash ());
@@ -216,20 +204,6 @@ public:
{
return m_ledgerMaster.getValidatedRange (minVal, maxVal);
}
bool getFullValidatedRange (
std::uint32_t& minVal, std::uint32_t& maxVal) override
{
return m_ledgerMaster.getFullValidatedRange (minVal, maxVal);
}
STValidation::ref getLastValidation () override
{
return mLastValidation;
}
void setLastValidation (STValidation::ref v) override
{
mLastValidation = v;
}
//
// Transaction operations.
@@ -290,23 +264,6 @@ public:
TransactionEngine& engine,
std::vector<TransactionStatus>& transactions);
Transaction::pointer findTransactionByID (
uint256 const& transactionID) override;
int findTransactionsByDestination (
std::list<Transaction::pointer>&,
RippleAddress const& destinationAccount,
std::uint32_t startLedgerSeq, std::uint32_t endLedgerSeq,
int maxTransactions) override;
//
// Directory functions.
//
STVector256 getDirNodeInfo (
Ledger::ref lrLedger, uint256 const& uRootIndex,
std::uint64_t& uNodePrevious, std::uint64_t& uNodeNext) override;
//
// Owner functions.
//
@@ -330,8 +287,7 @@ public:
bool recvValidation (
STValidation::ref val, std::string const& source) override;
void takePosition (
int seq, std::shared_ptr<SHAMap> const& position) override;
std::shared_ptr<SHAMap> getTXMap (uint256 const& hash);
bool hasTXSet (
const std::shared_ptr<Peer>& peer, uint256 const& set,
@@ -378,8 +334,6 @@ public:
*/
void setStateTimer () override;
void newLCL (
int proposers, int convergeTime, uint256 const& ledgerHash) override;
void needNetworkLedger () override
{
mNeedNetworkLedger = true;
@@ -396,44 +350,21 @@ public:
{
return !mNeedNetworkLedger && (mMode == omFULL);
}
void setProposing (bool p, bool v) override
{
mProposing = p;
mValidating = v;
}
bool isProposing () override
{
return mProposing;
}
bool isValidating () override
{
return mValidating;
}
bool isAmendmentBlocked () override
{
return m_amendmentBlocked;
}
void setAmendmentBlocked () override;
void consensusViewChange () override;
std::uint32_t getLastCloseTime () override
{
return mLastCloseTime;
}
void setLastCloseTime (std::uint32_t t) override
{
mLastCloseTime = t;
mConsensus->setLastCloseTime (t);
}
Json::Value getConsensusInfo () override;
Json::Value getServerInfo (bool human, bool admin) override;
void clearLedgerFetch () override;
Json::Value getLedgerFetchInfo () override;
std::uint32_t acceptLedger () override;
Proposals & peekStoredProposals () override
{
return mStoredProposals;
}
void storeProposal (
LedgerProposal::ref proposal, RippleAddress const& peerPublic) override;
uint256 getConsensusLCL () override;
void reportFeeChange () override;
@@ -441,11 +372,6 @@ public:
{
m_localTX->sweep (newValidLedger);
}
void addLocalTx (
Ledger::ref openLedger, STTx::ref txn) override
{
m_localTX->push_back (openLedger->getLedgerSeq(), txn);
}
std::size_t getLocalTxCount () override
{
return m_localTX->size ();
@@ -456,7 +382,7 @@ public:
std::string selection, AccountID const& account,
std::int32_t minLedger, std::int32_t maxLedger,
bool descending, std::uint32_t offset, int limit,
bool binary, bool count, bool bAdmin) override;
bool binary, bool count, bool bAdmin);
// Client information retrieval functions.
using NetworkOPs::AccountTxs;
@@ -571,6 +497,7 @@ private:
private:
clock_type& m_clock;
using SubMapType = hash_map <std::uint64_t, InfoSub::wptr>;
using SubInfoMapType = hash_map <AccountID, SubMapType>;
using subRpcMapType = hash_map<std::string, InfoSub::pointer>;
@@ -581,44 +508,25 @@ private:
beast::Journal m_journal;
std::unique_ptr <LocalTxs> m_localTX;
std::unique_ptr <FeeVote> m_feeVote;
LockType mSubLock;
std::atomic<OperatingMode> mMode;
std::atomic <bool> mNeedNetworkLedger;
bool mProposing;
bool mValidating;
bool m_amendmentBlocked;
beast::DeadlineTimer m_heartbeatTimer;
beast::DeadlineTimer m_clusterTimer;
std::shared_ptr<LedgerConsensus> mConsensus;
NetworkOPs::Proposals mStoredProposals;
std::unique_ptr<Consensus> mConsensus;
std::shared_ptr<LedgerConsensus> mLedgerConsensus;
LedgerMaster& m_ledgerMaster;
InboundLedger::pointer mAcquiringLedger;
int mCloseTimeOffset;
// The number of proposers who participated in the last ledger close
int lastCloseProposers_;
// How long the last ledger close took, in milliseconds
int lastCloseConvergeTook_;
// The hash of the last closed ledger
uint256 lastCloseHash_;
std::uint32_t mLastCloseTime;
std::uint32_t mLastValidationTime;
STValidation::pointer mLastValidation;
// Recent positions taken
std::map<uint256, std::pair<int, std::shared_ptr<SHAMap>>> mRecentPositions;
SubInfoMapType mSubAccount;
SubInfoMapType mSubRTAccount;
@@ -736,11 +644,11 @@ void NetworkOPsImp::processHeartbeatTimer ()
else if (mMode == omCONNECTED)
setMode (omCONNECTED);
if (!mConsensus)
if (!mLedgerConsensus)
tryStartConsensus ();
if (mConsensus)
mConsensus->timerEntry ();
if (mLedgerConsensus)
mLedgerConsensus->timerEntry ();
}
setHeartbeatTimer ();
@@ -800,10 +708,10 @@ std::string NetworkOPsImp::strOperatingMode () const
if (mMode == omFULL)
{
if (mProposing)
if (mConsensus->isProposing ())
return "proposing";
if (mValidating)
if (mConsensus->isValidating ())
return "validating";
}
@@ -832,8 +740,7 @@ std::uint32_t NetworkOPsImp::getNetworkTimeNC () const
std::uint32_t NetworkOPsImp::getCloseTimeNC () const
{
int offset;
return iToSeconds (getNetworkTimePT (offset) +
boost::posix_time::seconds (mCloseTimeOffset));
return getCloseTimeNC (offset);
}
std::uint32_t NetworkOPsImp::getCloseTimeNC (int& offset) const
@@ -842,17 +749,6 @@ std::uint32_t NetworkOPsImp::getCloseTimeNC (int& offset) const
boost::posix_time::seconds (mCloseTimeOffset));
}
std::uint32_t NetworkOPsImp::getValidationTimeNC ()
{
std::uint32_t vt = getNetworkTimeNC ();
if (vt <= mLastValidationTime)
vt = mLastValidationTime + 1;
mLastValidationTime = vt;
return vt;
}
void NetworkOPsImp::closeTimeOffset (int offset)
{
// take large offsets, ignore small offsets, push towards our wall time
@@ -889,11 +785,6 @@ std::uint32_t NetworkOPsImp::getCurrentLedgerID ()
return m_ledgerMaster.getCurrentLedger ()->getLedgerSeq ();
}
bool NetworkOPsImp::haveLedgerRange (std::uint32_t from, std::uint32_t to)
{
return m_ledgerMaster.haveLedgerRange (from, to);
}
bool NetworkOPsImp::haveLedger (std::uint32_t seq)
{
return m_ledgerMaster.haveLedger (seq);
@@ -906,19 +797,15 @@ std::uint32_t NetworkOPsImp::getValidatedSeq ()
bool NetworkOPsImp::isValidated (std::uint32_t seq, uint256 const& hash)
{
if (!isValidated (seq))
if (!haveLedger (seq))
return false;
if (seq > m_ledgerMaster.getValidatedLedger ()->getLedgerSeq ())
return false;
return m_ledgerMaster.getHashBySeq (seq) == hash;
}
bool NetworkOPsImp::isValidated (std::uint32_t seq)
{
// use when ledger was retrieved by seq
return haveLedger (seq) &&
seq <= m_ledgerMaster.getValidatedLedger ()->getLedgerSeq ();
}
void NetworkOPsImp::submitTransaction (Job&, STTx::pointer iTrans)
{
if (isNeedNetworkLedger ())
@@ -1175,8 +1062,9 @@ void NetworkOPsImp::apply (std::unique_lock<std::mutex>& batchLock)
if (addLocal)
{
addLocalTx (m_ledgerMaster.getCurrentLedger(),
e.transaction->getSTransaction());
m_localTX->push_back (
m_ledgerMaster.getCurrentLedgerIndex(),
e.transaction->getSTransaction());
}
if (e.applied ||
@@ -1235,70 +1123,6 @@ bool NetworkOPsImp::batchApply (Ledger::pointer& ledger,
return applied;
}
Transaction::pointer NetworkOPsImp::findTransactionByID (
uint256 const& transactionID)
{
return Transaction::load (transactionID);
}
int NetworkOPsImp::findTransactionsByDestination (
std::list<Transaction::pointer>& txns,
RippleAddress const& destinationAccount, std::uint32_t startLedgerSeq,
std::uint32_t endLedgerSeq, int maxTransactions)
{
// WRITEME
return 0;
}
//
// Directory functions
//
// <-- false : no entrieS
STVector256 NetworkOPsImp::getDirNodeInfo (
Ledger::ref lrLedger,
uint256 const& uNodeIndex,
std::uint64_t& uNodePrevious,
std::uint64_t& uNodeNext)
{
STVector256 svIndexes;
auto const sleNode = cachedRead(*lrLedger, uNodeIndex,
getApp().getSLECache(), ltDIR_NODE);
if (sleNode)
{
m_journal.debug
<< "getDirNodeInfo: node index: " << to_string (uNodeIndex);
m_journal.trace
<< "getDirNodeInfo: first: "
<< strHex (sleNode->getFieldU64 (sfIndexPrevious));
m_journal.trace
<< "getDirNodeInfo: last: "
<< strHex (sleNode->getFieldU64 (sfIndexNext));
uNodePrevious = sleNode->getFieldU64 (sfIndexPrevious);
uNodeNext = sleNode->getFieldU64 (sfIndexNext);
svIndexes = sleNode->getFieldV256 (sfIndexes);
m_journal.trace
<< "getDirNodeInfo: first: " << strHex (uNodePrevious);
m_journal.trace
<< "getDirNodeInfo: last: " << strHex (uNodeNext);
}
else
{
m_journal.info
<< "getDirNodeInfo: node index: NOT FOUND: "
<< to_string (uNodeIndex);
uNodePrevious = 0;
uNodeNext = 0;
}
return svIndexes;
}
//
// Owner functions
//
@@ -1443,7 +1267,7 @@ void NetworkOPsImp::tryStartConsensus ()
}
}
if ((!mConsensus) && (mMode != omDISCONNECTED))
if ((!mLedgerConsensus) && (mMode != omDISCONNECTED))
beginConsensus (networkClosed, m_ledgerMaster.getCurrentLedger ());
}
@@ -1640,18 +1464,16 @@ bool NetworkOPsImp::beginConsensus (
m_ledgerMaster.getClosedLedger ()->getHash ());
// Create a consensus object to get consensus on this ledger
assert (!mConsensus);
assert (!mLedgerConsensus);
prevLedger->setImmutable ();
mConsensus = make_LedgerConsensus (
lastCloseProposers_,
lastCloseConvergeTook_,
mLedgerConsensus = mConsensus->startRound (
getApp().getInboundTransactions(),
*m_localTX,
m_ledgerMaster,
networkClosed,
prevLedger,
m_ledgerMaster.getCurrentLedger ()->getCloseTimeNC (),
*m_feeVote);
m_ledgerMaster.getCurrentLedger ()->getCloseTimeNC ());
m_journal.debug << "Initiating consensus engine";
return true;
@@ -1659,7 +1481,7 @@ bool NetworkOPsImp::beginConsensus (
bool NetworkOPsImp::haveConsensusObject ()
{
if (mConsensus != nullptr)
if (mLedgerConsensus != nullptr)
return true;
if ((mMode == omFULL) || (mMode == omTRACKING))
@@ -1677,13 +1499,13 @@ bool NetworkOPsImp::haveConsensusObject ()
{
m_journal.info << "Beginning consensus due to peer action";
if ( ((mMode == omTRACKING) || (mMode == omSYNCING)) &&
(lastCloseProposers_ >= m_ledgerMaster.getMinValidations()) )
(mConsensus->getLastCloseProposers() >= m_ledgerMaster.getMinValidations()) )
setMode (omFULL);
beginConsensus (networkClosed, m_ledgerMaster.getCurrentLedger ());
}
}
return mConsensus != nullptr;
return mLedgerConsensus != nullptr;
}
uint256 NetworkOPsImp::getConsensusLCL ()
@@ -1691,7 +1513,7 @@ uint256 NetworkOPsImp::getConsensusLCL ()
if (!haveConsensusObject ())
return uint256 ();
return mConsensus->getLCL ();
return mLedgerConsensus->getLCL ();
}
void NetworkOPsImp::processTrustedProposal (
@@ -1712,45 +1534,23 @@ void NetworkOPsImp::processTrustedProposal (
}
else
{
storeProposal (proposal, nodePublic);
mConsensus->storeProposal (proposal, nodePublic);
if (mConsensus->getLCL () == proposal->getPrevLedger ())
if (mLedgerConsensus->getLCL () == proposal->getPrevLedger ())
{
relay = mConsensus->peerPosition (proposal);
relay = mLedgerConsensus->peerPosition (proposal);
m_journal.trace
<< "Proposal processing finished, relay=" << relay;
}
}
if (relay)
getApp().overlay().relay(*set,
proposal->getSuppressionID());
getApp().overlay().relay(*set, proposal->getSuppressionID());
else
m_journal.info << "Not relaying trusted proposal";
}
}
// Must be called while holding the master lock
void
NetworkOPsImp::takePosition (int seq, std::shared_ptr<SHAMap> const& position)
{
mRecentPositions[position->getHash ()] = std::make_pair (seq, position);
if (mRecentPositions.size () > 4)
{
for (auto i = mRecentPositions.begin (); i != mRecentPositions.end ();)
{
if (i->second.first < (seq - 2))
{
mRecentPositions.erase (i);
return;
}
++i;
}
}
}
void
NetworkOPsImp::mapComplete (uint256 const& hash,
std::shared_ptr<SHAMap> const& map)
@@ -1758,7 +1558,7 @@ NetworkOPsImp::mapComplete (uint256 const& hash,
std::lock_guard<Application::MutexType> lock(getApp().getMasterMutex());
if (haveConsensusObject ())
mConsensus->mapComplete (hash, map, true);
mLedgerConsensus->mapComplete (hash, map, true);
}
void NetworkOPsImp::endConsensus (bool correctLCL)
@@ -1777,7 +1577,7 @@ void NetworkOPsImp::endConsensus (bool correctLCL)
}
}
mConsensus = std::shared_ptr<LedgerConsensus> ();
mLedgerConsensus = std::shared_ptr<LedgerConsensus> ();
}
void NetworkOPsImp::consensusViewChange ()
@@ -1946,7 +1746,7 @@ NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs (
// can be called with no locks
AccountTxs ret;
std::string sql = NetworkOPsImp::transactionsSQL (
std::string sql = transactionsSQL (
"AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta", account,
minLedger, maxLedger, descending, offset, limit, false, false, bAdmin);
@@ -2009,7 +1809,7 @@ std::vector<NetworkOPsImp::txnMetaLedgerType> NetworkOPsImp::getAccountTxsB (
// can be called with no locks
std::vector<txnMetaLedgerType> ret;
std::string sql = NetworkOPsImp::transactionsSQL (
std::string sql = transactionsSQL (
"AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta", account,
minLedger, maxLedger, descending, offset, limit, true/*binary*/, false,
bAdmin);
@@ -2109,8 +1909,8 @@ bool NetworkOPsImp::recvValidation (
Json::Value NetworkOPsImp::getConsensusInfo ()
{
if (mConsensus)
return mConsensus->getJson (true);
if (mLedgerConsensus)
return mLedgerConsensus->getJson (true);
Json::Value info = Json::objectValue;
info[jss::consensus] = "none";
@@ -2169,23 +1969,23 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
info[jss::peers] = Json::UInt (getApp ().overlay ().size ());
Json::Value lastClose = Json::objectValue;
lastClose[jss::proposers] = lastCloseProposers_;
lastClose[jss::proposers] = mConsensus->getLastCloseProposers();
if (human)
{
lastClose[jss::converge_time_s] = static_cast<double> (
lastCloseConvergeTook_) / 1000.0;
mConsensus->getLastCloseDuration()) / 1000.0;
}
else
{
lastClose[jss::converge_time] =
Json::Int (lastCloseConvergeTook_);
Json::Int (mConsensus->getLastCloseDuration());
}
info[jss::last_close] = lastClose;
// if (mConsensus)
// info[jss::consensus] = mConsensus->getJson();
// if (mLedgerConsensus)
// info[jss::consensus] = mLedgerConsensus->getJson();
if (admin)
info[jss::load] = m_job_queue.getJson ();
@@ -2279,7 +2079,7 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
else
info[jss::closed_ledger] = l;
Ledger::pointer lpPublished = getPublishedLedger ();
Ledger::pointer lpPublished = m_ledgerMaster.getPublishedLedger ();
if (!lpPublished)
info[jss::published_ledger] = "none";
else if (lpPublished->getLedgerSeq() != lpClosed->getLedgerSeq())
@@ -2679,15 +2479,6 @@ bool NetworkOPsImp::unsubBook (std::uint64_t uSeq, Book const& book)
return true;
}
void NetworkOPsImp::newLCL (
int proposers, int convergeTime, uint256 const& ledgerHash)
{
assert (convergeTime);
lastCloseProposers_ = proposers;
lastCloseConvergeTook_ = convergeTime;
lastCloseHash_ = ledgerHash;
}
std::uint32_t NetworkOPsImp::acceptLedger ()
{
// This code-path is exclusively used when the server is in standalone
@@ -2702,21 +2493,10 @@ std::uint32_t NetworkOPsImp::acceptLedger ()
beginConsensus (
m_ledgerMaster.getClosedLedger ()->getHash (),
m_ledgerMaster.getCurrentLedger ());
mConsensus->simulate ();
mLedgerConsensus->simulate ();
return m_ledgerMaster.getCurrentLedger ()->getLedgerSeq ();
}
void NetworkOPsImp::storeProposal (
LedgerProposal::ref proposal, RippleAddress const& peerPublic)
{
auto& props = mStoredProposals[peerPublic.getNodeID ()];
if (props.size () >= (unsigned) (lastCloseProposers_ + 10))
props.pop_front ();
props.push_back (proposal);
}
// <-- bool: true=added, false=already there
bool NetworkOPsImp::subLedger (InfoSub::ref isrListener, Json::Value& jvResult)
{

View File

@@ -39,7 +39,6 @@ namespace ripple {
// Master operational handler, server sequencer, network tracker
class Peer;
class LedgerConsensus;
class LedgerMaster;
// This is the primary interface into the "client" portion of the program.
@@ -74,13 +73,6 @@ protected:
public:
using clock_type = beast::abstract_clock <std::chrono::steady_clock>;
enum Fault
{
// exceptions these functions can throw
IO_ERROR = 1,
NO_NETWORK = 2,
};
enum OperatingMode
{
// how we process transactions or account balance requests
@@ -101,10 +93,6 @@ public:
return noMeansDont ? FailHard::yes : FailHard::no;
}
// VFALCO TODO Fix OrderBookDB to not need this unrelated type.
//
using SubMapType = hash_map <std::uint64_t, InfoSub::wptr>;
public:
virtual ~NetworkOPs () = 0;
@@ -117,10 +105,7 @@ public:
virtual std::uint32_t getNetworkTimeNC () const = 0;
// Our best estimate of current ledger close time
virtual std::uint32_t getCloseTimeNC () const = 0;
// Use *only* to timestamp our own validation
virtual std::uint32_t getValidationTimeNC () = 0;
virtual void closeTimeOffset (int) = 0;
virtual boost::posix_time::ptime getNetworkTimePT (int& offset) const = 0;
virtual std::uint32_t getLedgerID (uint256 const& hash) = 0;
virtual std::uint32_t getCurrentLedgerID () = 0;
@@ -128,7 +113,6 @@ public:
virtual std::string strOperatingMode () const = 0;
virtual Ledger::pointer getClosedLedger () = 0;
virtual Ledger::pointer getValidatedLedger () = 0;
virtual Ledger::pointer getPublishedLedger () = 0;
virtual Ledger::pointer getCurrentLedger () = 0;
virtual Ledger::pointer getLedgerByHash (uint256 const& hash) = 0;
virtual Ledger::pointer getLedgerBySeq (const std::uint32_t seq) = 0;
@@ -137,17 +121,10 @@ public:
virtual uint256 getClosedLedgerHash () = 0;
// Do we have this inclusive range of ledgers in our database
virtual bool haveLedgerRange (std::uint32_t from, std::uint32_t to) = 0;
virtual bool haveLedger (std::uint32_t seq) = 0;
virtual std::uint32_t getValidatedSeq () = 0;
virtual bool isValidated (std::uint32_t seq) = 0;
virtual bool isValidated (std::uint32_t seq, uint256 const& hash) = 0;
virtual bool isValidated (Ledger::ref l) = 0;
virtual bool getValidatedRange (std::uint32_t& minVal, std::uint32_t& maxVal) = 0;
virtual bool getFullValidatedRange (std::uint32_t& minVal, std::uint32_t& maxVal) = 0;
virtual STValidation::ref getLastValidation () = 0;
virtual void setLastValidation (STValidation::ref v) = 0;
//--------------------------------------------------------------------------
//
@@ -155,8 +132,6 @@ public:
//
// must complete immediately
// VFALCO TODO Make this a TxCallback structure
using stCallback = std::function<void (Transaction::pointer, TER)>;
virtual void submitTransaction (Job&, STTx::pointer) = 0;
/**
@@ -170,19 +145,6 @@ public:
*/
virtual void processTransaction (Transaction::pointer transaction,
bool bAdmin, bool bLocal, FailHard failType) = 0;
virtual Transaction::pointer findTransactionByID (uint256 const& transactionID) = 0;
virtual int findTransactionsByDestination (std::list<Transaction::pointer>&,
RippleAddress const& destinationAccount, std::uint32_t startLedgerSeq,
std::uint32_t endLedgerSeq, int maxTransactions) = 0;
//--------------------------------------------------------------------------
//
// Directory functions
//
virtual STVector256 getDirNodeInfo (Ledger::ref lrLedger,
uint256 const& uRootIndex, std::uint64_t& uNodePrevious,
std::uint64_t& uNodeNext) = 0;
//--------------------------------------------------------------------------
//
@@ -217,9 +179,6 @@ public:
virtual bool recvValidation (STValidation::ref val,
std::string const& source) = 0;
virtual void takePosition (int seq,
std::shared_ptr<SHAMap> const& position) = 0;
virtual void mapComplete (uint256 const& hash,
std::shared_ptr<SHAMap> const& map) = 0;
@@ -241,20 +200,16 @@ public:
virtual void setStandAlone () = 0;
virtual void setStateTimer () = 0;
virtual void newLCL (
int proposers, int convergeTime, uint256 const& ledgerHash) = 0;
// VFALCO TODO rename to setNeedNetworkLedger
virtual void needNetworkLedger () = 0;
virtual void clearNeedNetworkLedger () = 0;
virtual bool isNeedNetworkLedger () = 0;
virtual bool isFull () = 0;
virtual void setProposing (bool isProposing, bool isValidating) = 0;
virtual bool isProposing () = 0;
virtual bool isValidating () = 0;
virtual bool isAmendmentBlocked () = 0;
virtual void setAmendmentBlocked () = 0;
virtual void consensusViewChange () = 0;
virtual std::uint32_t getLastCloseTime () = 0;
// FIXME(NIKB): Remove the need for this function
virtual void setLastCloseTime (std::uint32_t t) = 0;
virtual Json::Value getConsensusInfo () = 0;
@@ -270,26 +225,13 @@ public:
*/
virtual std::uint32_t acceptLedger () = 0;
using Proposals = hash_map <NodeID, std::deque<LedgerProposal::pointer>>;
virtual Proposals& peekStoredProposals () = 0;
virtual void storeProposal (LedgerProposal::ref proposal,
RippleAddress const& peerPublic) = 0;
virtual uint256 getConsensusLCL () = 0;
virtual void reportFeeChange () = 0;
virtual void updateLocalTx (Ledger::ref newValidLedger) = 0;
virtual void addLocalTx (Ledger::ref openLedger, STTx::ref txn) = 0;
virtual std::size_t getLocalTxCount () = 0;
//Helper function to generate SQL query to get transactions
virtual std::string transactionsSQL (std::string selection,
AccountID const& account, std::int32_t minLedger, std::int32_t maxLedger,
bool descending, std::uint32_t offset, int limit, bool binary,
bool count, bool bAdmin) = 0;
// client information retrieval functions
using AccountTx = std::pair<Transaction::pointer, TransactionMetaSet::pointer>;
using AccountTxs = std::vector<AccountTx>;

View File

@@ -20,8 +20,9 @@
#ifndef RIPPLE_APP_TX_LOCALTXS_H_INCLUDED
#define RIPPLE_APP_TX_LOCALTXS_H_INCLUDED
#include <ripple/app/tx/TransactionEngine.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <beast/cxx14/memory.h> // <memory>
namespace ripple {
@@ -32,16 +33,13 @@ namespace ripple {
class LocalTxs
{
public:
virtual ~LocalTxs () = default;
static std::unique_ptr<LocalTxs> New ();
// Add a new local transaction
virtual void push_back (LedgerIndex index, STTx::ref txn) = 0;
// Apply local transactions to a new open ledger
virtual void apply (TransactionEngine&) = 0;
// Return the set of local transactions to a new open ledger
virtual CanonicalTXSet getTxSet () = 0;
// Remove obsolete transactions based on a new fully-valid ledger
virtual void sweep (Ledger::ref validLedger) = 0;
@@ -49,6 +47,9 @@ public:
virtual std::size_t size () = 0;
};
std::unique_ptr<LocalTxs>
make_LocalTxs ();
} // ripple
#endif

View File

@@ -20,7 +20,6 @@
#include <BeastConfig.h>
#include <ripple/app/tx/LocalTxs.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/protocol/Indexes.h>
/*
@@ -107,12 +106,11 @@ private:
//------------------------------------------------------------------------------
class LocalTxsImp : public LocalTxs
class LocalTxsImp
: public LocalTxs
{
public:
LocalTxsImp()
{ }
LocalTxsImp() = default;
// Add a new transaction to the set of local transactions
void push_back (LedgerIndex index, STTx::ref txn) override
@@ -138,9 +136,9 @@ public:
return false;
}
void apply (TransactionEngine& engine) override
CanonicalTXSet
getTxSet () override
{
CanonicalTXSet tset (uint256 {});
// Get the set of local transactions as a canonical
@@ -148,24 +146,11 @@ public:
{
std::lock_guard <std::mutex> lock (m_lock);
for (auto& it : m_txns)
for (auto const& it : m_txns)
tset.push_back (it.getTX());
}
for (auto it : tset)
{
try
{
engine.applyTransaction (*it.second, tapOPEN_LEDGER);
}
catch (...)
{
// Nothing special we need to do.
// It's possible a cleverly malformed transaction or
// corrupt back end database could cause an exception
// during transaction processing.
}
}
return tset;
}
// Remove transactions that have either been accepted into a fully-validated
@@ -191,14 +176,14 @@ public:
}
private:
std::mutex m_lock;
std::list <LocalTx> m_txns;
};
std::unique_ptr <LocalTxs> LocalTxs::New()
std::unique_ptr<LocalTxs>
make_LocalTxs ()
{
return std::make_unique <LocalTxsImp> ();
return std::make_unique<LocalTxsImp> ();
}
} // ripple

View File

@@ -30,11 +30,12 @@
#include <ripple/app/ledger/OrderBookDB.cpp>
#include <ripple/app/ledger/TransactionStateSF.cpp>
#include <ripple/app/ledger/impl/ConsensusImp.cpp>
#include <ripple/app/ledger/impl/DisputedTx.cpp>
#include <ripple/app/ledger/impl/InboundLedger.cpp>
#include <ripple/app/ledger/impl/InboundLedgers.cpp>
#include <ripple/app/ledger/impl/LedgerCleaner.cpp>
#include <ripple/app/ledger/impl/LedgerConsensus.cpp>
#include <ripple/app/ledger/impl/LedgerConsensusImp.cpp>
#include <ripple/app/ledger/impl/LedgerFees.cpp>
#include <ripple/app/ledger/impl/LedgerMaster.cpp>
#include <ripple/app/ledger/impl/LedgerTiming.cpp>