mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 14:05:51 +00:00
Expose consensus parameters for simulation (RIPD-1355)
This commit is contained in:
@@ -1859,16 +1859,18 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\consensus\Consensus.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\Consensus.h">
|
<ClInclude Include="..\..\src\ripple\consensus\Consensus.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple\consensus\ConsensusParms.h">
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\ConsensusProposal.h">
|
<ClInclude Include="..\..\src\ripple\consensus\ConsensusProposal.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\DisputedTx.h">
|
<ClInclude Include="..\..\src\ripple\consensus\DisputedTx.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\consensus\LedgerTiming.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\LedgerTiming.h">
|
<ClInclude Include="..\..\src\ripple\consensus\LedgerTiming.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\Validations.h">
|
<ClInclude Include="..\..\src\ripple\consensus\Validations.h">
|
||||||
|
|||||||
@@ -2502,18 +2502,21 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
||||||
<Filter>ripple\conditions\impl</Filter>
|
<Filter>ripple\conditions\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\consensus\Consensus.cpp">
|
||||||
|
<Filter>ripple\consensus</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\Consensus.h">
|
<ClInclude Include="..\..\src\ripple\consensus\Consensus.h">
|
||||||
<Filter>ripple\consensus</Filter>
|
<Filter>ripple\consensus</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple\consensus\ConsensusParms.h">
|
||||||
|
<Filter>ripple\consensus</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\ConsensusProposal.h">
|
<ClInclude Include="..\..\src\ripple\consensus\ConsensusProposal.h">
|
||||||
<Filter>ripple\consensus</Filter>
|
<Filter>ripple\consensus</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\DisputedTx.h">
|
<ClInclude Include="..\..\src\ripple\consensus\DisputedTx.h">
|
||||||
<Filter>ripple\consensus</Filter>
|
<Filter>ripple\consensus</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\consensus\LedgerTiming.cpp">
|
|
||||||
<Filter>ripple\consensus</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="..\..\src\ripple\consensus\LedgerTiming.h">
|
<ClInclude Include="..\..\src\ripple\consensus\LedgerTiming.h">
|
||||||
<Filter>ripple\consensus</Filter>
|
<Filter>ripple\consensus</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ INPUT = \
|
|||||||
../src/ripple/consensus/DisputedTx.h \
|
../src/ripple/consensus/DisputedTx.h \
|
||||||
../src/ripple/consensus/LedgerTiming.h \
|
../src/ripple/consensus/LedgerTiming.h \
|
||||||
../src/ripple/consensus/Validations.h \
|
../src/ripple/consensus/Validations.h \
|
||||||
|
../src/ripple/consensus/ConsensusParms.h \
|
||||||
../src/ripple/app/consensus/RCLCxTx.h \
|
../src/ripple/app/consensus/RCLCxTx.h \
|
||||||
../src/ripple/app/consensus/RCLCxLedger.h \
|
../src/ripple/app/consensus/RCLCxLedger.h \
|
||||||
../src/ripple/app/consensus/RCLConsensus.h \
|
../src/ripple/app/consensus/RCLConsensus.h \
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ RCLConsensus::RCLConsensus(
|
|||||||
InboundTransactions& inboundTransactions,
|
InboundTransactions& inboundTransactions,
|
||||||
typename Base::clock_type const& clock,
|
typename Base::clock_type const& clock,
|
||||||
beast::Journal journal)
|
beast::Journal journal)
|
||||||
: Base(clock, journal)
|
: Base(clock, ConsensusParms{}, journal)
|
||||||
, app_(app)
|
, app_(app)
|
||||||
, feeVote_(std::move(feeVote))
|
, feeVote_(std::move(feeVote))
|
||||||
, ledgerMaster_(ledgerMaster)
|
, ledgerMaster_(ledgerMaster)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <ripple/app/ledger/AcceptedLedger.h>
|
#include <ripple/app/ledger/AcceptedLedger.h>
|
||||||
#include <ripple/app/ledger/InboundLedgers.h>
|
#include <ripple/app/ledger/InboundLedgers.h>
|
||||||
#include <ripple/app/ledger/LedgerMaster.h>
|
#include <ripple/app/ledger/LedgerMaster.h>
|
||||||
#include <ripple/consensus/LedgerTiming.h>
|
#include <ripple/consensus/ConsensusParms.h>
|
||||||
#include <ripple/app/ledger/LedgerToJson.h>
|
#include <ripple/app/ledger/LedgerToJson.h>
|
||||||
#include <ripple/app/ledger/LocalTxs.h>
|
#include <ripple/app/ledger/LocalTxs.h>
|
||||||
#include <ripple/app/ledger/OpenLedger.h>
|
#include <ripple/app/ledger/OpenLedger.h>
|
||||||
@@ -639,7 +639,7 @@ void NetworkOPsImp::setStateTimer ()
|
|||||||
|
|
||||||
void NetworkOPsImp::setHeartbeatTimer ()
|
void NetworkOPsImp::setHeartbeatTimer ()
|
||||||
{
|
{
|
||||||
m_heartbeatTimer.setExpiration (LEDGER_GRANULARITY);
|
m_heartbeatTimer.setExpiration (mConsensus->parms().ledgerGRANULARITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkOPsImp::setClusterTimer ()
|
void NetworkOPsImp::setClusterTimer ()
|
||||||
|
|||||||
@@ -19,9 +19,7 @@
|
|||||||
|
|
||||||
#include <BeastConfig.h>
|
#include <BeastConfig.h>
|
||||||
#include <ripple/basics/Log.h>
|
#include <ripple/basics/Log.h>
|
||||||
#include <ripple/consensus/LedgerTiming.h>
|
#include <ripple/consensus/Consensus.h>
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -35,11 +33,13 @@ shouldCloseLedger(
|
|||||||
std::chrono::milliseconds
|
std::chrono::milliseconds
|
||||||
timeSincePrevClose, // Time since last ledger's close time
|
timeSincePrevClose, // Time since last ledger's close time
|
||||||
std::chrono::milliseconds openTime, // Time waiting to close this ledger
|
std::chrono::milliseconds openTime, // Time waiting to close this ledger
|
||||||
std::chrono::seconds idleInterval,
|
std::chrono::milliseconds idleInterval,
|
||||||
|
ConsensusParms const& parms,
|
||||||
beast::Journal j)
|
beast::Journal j)
|
||||||
{
|
{
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
if ((prevRoundTime < -1s) || (prevRoundTime > 10min) || (timeSincePrevClose > 10min))
|
if ((prevRoundTime < -1s) || (prevRoundTime > 10min) ||
|
||||||
|
(timeSincePrevClose > 10min))
|
||||||
{
|
{
|
||||||
// These are unexpected cases, we just close the ledger
|
// These are unexpected cases, we just close the ledger
|
||||||
JLOG(j.warn()) << "shouldCloseLedger Trans="
|
JLOG(j.warn()) << "shouldCloseLedger Trans="
|
||||||
@@ -64,7 +64,7 @@ shouldCloseLedger(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Preserve minimum ledger open time
|
// Preserve minimum ledger open time
|
||||||
if (openTime < LEDGER_MIN_CLOSE)
|
if (openTime < parms.ledgerMIN_CLOSE)
|
||||||
{
|
{
|
||||||
JLOG(j.debug()) << "Must wait minimum time before closing";
|
JLOG(j.debug()) << "Must wait minimum time before closing";
|
||||||
return false;
|
return false;
|
||||||
@@ -84,7 +84,11 @@ shouldCloseLedger(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
checkConsensusReached(std::size_t agreeing, std::size_t total, bool count_self)
|
checkConsensusReached(
|
||||||
|
std::size_t agreeing,
|
||||||
|
std::size_t total,
|
||||||
|
bool count_self,
|
||||||
|
std::size_t minConsensusPct)
|
||||||
{
|
{
|
||||||
// If we are alone, we have a consensus
|
// If we are alone, we have a consensus
|
||||||
if (total == 0)
|
if (total == 0)
|
||||||
@@ -96,9 +100,9 @@ checkConsensusReached(std::size_t agreeing, std::size_t total, bool count_self)
|
|||||||
++total;
|
++total;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentPercentage = (agreeing * 100) / total;
|
std::size_t currentPercentage = (agreeing * 100) / total;
|
||||||
|
|
||||||
return currentPercentage > minimumConsensusPercentage;
|
return currentPercentage > minConsensusPct;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsensusState
|
ConsensusState
|
||||||
@@ -109,6 +113,7 @@ checkConsensus(
|
|||||||
std::size_t currentFinished,
|
std::size_t currentFinished,
|
||||||
std::chrono::milliseconds previousAgreeTime,
|
std::chrono::milliseconds previousAgreeTime,
|
||||||
std::chrono::milliseconds currentAgreeTime,
|
std::chrono::milliseconds currentAgreeTime,
|
||||||
|
ConsensusParms const& parms,
|
||||||
bool proposing,
|
bool proposing,
|
||||||
beast::Journal j)
|
beast::Journal j)
|
||||||
{
|
{
|
||||||
@@ -118,14 +123,14 @@ checkConsensus(
|
|||||||
<< " time=" << currentAgreeTime.count() << "/"
|
<< " time=" << currentAgreeTime.count() << "/"
|
||||||
<< previousAgreeTime.count();
|
<< previousAgreeTime.count();
|
||||||
|
|
||||||
if (currentAgreeTime <= LEDGER_MIN_CONSENSUS)
|
if (currentAgreeTime <= parms.ledgerMIN_CONSENSUS)
|
||||||
return ConsensusState::No;
|
return ConsensusState::No;
|
||||||
|
|
||||||
if (currentProposers < (prevProposers * 3 / 4))
|
if (currentProposers < (prevProposers * 3 / 4))
|
||||||
{
|
{
|
||||||
// Less than 3/4 of the last ledger's proposers are present; don't
|
// Less than 3/4 of the last ledger's proposers are present; don't
|
||||||
// rush: we may need more time.
|
// rush: we may need more time.
|
||||||
if (currentAgreeTime < (previousAgreeTime + LEDGER_MIN_CONSENSUS))
|
if (currentAgreeTime < (previousAgreeTime + parms.ledgerMIN_CONSENSUS))
|
||||||
{
|
{
|
||||||
JLOG(j.trace()) << "too fast, not enough proposers";
|
JLOG(j.trace()) << "too fast, not enough proposers";
|
||||||
return ConsensusState::No;
|
return ConsensusState::No;
|
||||||
@@ -134,7 +139,8 @@ checkConsensus(
|
|||||||
|
|
||||||
// Have we, together with the nodes on our UNL list, reached the threshold
|
// Have we, together with the nodes on our UNL list, reached the threshold
|
||||||
// to declare consensus?
|
// to declare consensus?
|
||||||
if (checkConsensusReached(currentAgree, currentProposers, proposing))
|
if (checkConsensusReached(
|
||||||
|
currentAgree, currentProposers, proposing, parms.minCONSENSUS_PCT))
|
||||||
{
|
{
|
||||||
JLOG(j.debug()) << "normal consensus";
|
JLOG(j.debug()) << "normal consensus";
|
||||||
return ConsensusState::Yes;
|
return ConsensusState::Yes;
|
||||||
@@ -142,7 +148,8 @@ checkConsensus(
|
|||||||
|
|
||||||
// Have sufficient nodes on our UNL list moved on and reached the threshold
|
// Have sufficient nodes on our UNL list moved on and reached the threshold
|
||||||
// to declare consensus?
|
// to declare consensus?
|
||||||
if (checkConsensusReached(currentFinished, currentProposers, false))
|
if (checkConsensusReached(
|
||||||
|
currentFinished, currentProposers, false, parms.minCONSENSUS_PCT))
|
||||||
{
|
{
|
||||||
JLOG(j.warn()) << "We see no consensus, but 80% of nodes have moved on";
|
JLOG(j.warn()) << "We see no consensus, but 80% of nodes have moved on";
|
||||||
return ConsensusState::MovedOn;
|
return ConsensusState::MovedOn;
|
||||||
@@ -153,4 +160,4 @@ checkConsensus(
|
|||||||
return ConsensusState::No;
|
return ConsensusState::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ripple
|
} // namespace ripple
|
||||||
@@ -24,11 +24,79 @@
|
|||||||
#include <ripple/basics/chrono.h>
|
#include <ripple/basics/chrono.h>
|
||||||
#include <ripple/beast/utility/Journal.h>
|
#include <ripple/beast/utility/Journal.h>
|
||||||
#include <ripple/consensus/ConsensusProposal.h>
|
#include <ripple/consensus/ConsensusProposal.h>
|
||||||
|
#include <ripple/consensus/ConsensusParms.h>
|
||||||
|
#include <ripple/consensus/LedgerTiming.h>
|
||||||
#include <ripple/consensus/DisputedTx.h>
|
#include <ripple/consensus/DisputedTx.h>
|
||||||
#include <ripple/json/json_writer.h>
|
#include <ripple/json/json_writer.h>
|
||||||
|
|
||||||
namespace ripple {
|
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 prevProposers 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 prevRoundTime time for the previous ledger to reach consensus
|
||||||
|
@param timeSincePrevClose time since the previous ledger's (possibly rounded)
|
||||||
|
close time
|
||||||
|
@param openTime duration this ledger has been open
|
||||||
|
@param idleInterval the network's desired idle interval
|
||||||
|
@param parms Consensus constant parameters
|
||||||
|
@param j journal for logging
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
shouldCloseLedger(
|
||||||
|
bool anyTransactions,
|
||||||
|
std::size_t prevProposers,
|
||||||
|
std::size_t proposersClosed,
|
||||||
|
std::size_t proposersValidated,
|
||||||
|
std::chrono::milliseconds prevRoundTime,
|
||||||
|
std::chrono::milliseconds timeSincePrevClose,
|
||||||
|
std::chrono::milliseconds openTime,
|
||||||
|
std::chrono::milliseconds idleInterval,
|
||||||
|
ConsensusParms const & parms,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
|
||||||
|
/** Whether we have or don't have a consensus */
|
||||||
|
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 prevProposers 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
|
||||||
|
@param parms Consensus constant parameters
|
||||||
|
@param proposing whether we should count ourselves
|
||||||
|
@param j journal for logging
|
||||||
|
*/
|
||||||
|
ConsensusState
|
||||||
|
checkConsensus(
|
||||||
|
std::size_t prevProposers,
|
||||||
|
std::size_t currentProposers,
|
||||||
|
std::size_t currentAgree,
|
||||||
|
std::size_t currentFinished,
|
||||||
|
std::chrono::milliseconds previousAgreeTime,
|
||||||
|
std::chrono::milliseconds currentAgreeTime,
|
||||||
|
ConsensusParms const & parms,
|
||||||
|
bool proposing,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
/** Generic implementation of consensus algorithm.
|
/** Generic implementation of consensus algorithm.
|
||||||
|
|
||||||
Achieves consensus on the next ledger.
|
Achieves consensus on the next ledger.
|
||||||
@@ -351,9 +419,10 @@ public:
|
|||||||
/** Constructor.
|
/** Constructor.
|
||||||
|
|
||||||
@param clock The clock used to internally sample consensus progress
|
@param clock The clock used to internally sample consensus progress
|
||||||
|
@param p Consensus parameters to use
|
||||||
@param j The journal to log debug output
|
@param j The journal to log debug output
|
||||||
*/
|
*/
|
||||||
Consensus(clock_type const& clock, beast::Journal j);
|
Consensus(clock_type const& clock, ConsensusParms const & p, beast::Journal j);
|
||||||
|
|
||||||
/** Kick-off the next round of consensus.
|
/** Kick-off the next round of consensus.
|
||||||
|
|
||||||
@@ -474,6 +543,13 @@ public:
|
|||||||
Json::Value
|
Json::Value
|
||||||
getJson(bool full) const;
|
getJson(bool full) const;
|
||||||
|
|
||||||
|
/** Get the consensus parameters
|
||||||
|
*/
|
||||||
|
ConsensusParms const &
|
||||||
|
parms() const
|
||||||
|
{
|
||||||
|
return parms_;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Prevent deleting derived instance through base pointer
|
// Prevent deleting derived instance through base pointer
|
||||||
@@ -584,7 +660,7 @@ private:
|
|||||||
NetClock::duration closeResolution_ = ledgerDefaultTimeResolution;
|
NetClock::duration closeResolution_ = ledgerDefaultTimeResolution;
|
||||||
|
|
||||||
// Time it took for the last consensus round to converge
|
// Time it took for the last consensus round to converge
|
||||||
std::chrono::milliseconds prevRoundTime_ = LEDGER_IDLE_INTERVAL;
|
std::chrono::milliseconds prevRoundTime_;
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Network time measurements of consensus progress
|
// Network time measurements of consensus progress
|
||||||
@@ -618,6 +694,9 @@ private:
|
|||||||
// nodes that have bowed out of this consensus process
|
// nodes that have bowed out of this consensus process
|
||||||
hash_set<NodeID_t> deadNodes_;
|
hash_set<NodeID_t> deadNodes_;
|
||||||
|
|
||||||
|
// Parameters that control consensus algorithm
|
||||||
|
ConsensusParms const parms_;
|
||||||
|
|
||||||
// Journal for debugging
|
// Journal for debugging
|
||||||
beast::Journal j_;
|
beast::Journal j_;
|
||||||
};
|
};
|
||||||
@@ -625,9 +704,12 @@ private:
|
|||||||
template <class Derived, class Traits>
|
template <class Derived, class Traits>
|
||||||
Consensus<Derived, Traits>::Consensus(
|
Consensus<Derived, Traits>::Consensus(
|
||||||
clock_type const& clock,
|
clock_type const& clock,
|
||||||
|
ConsensusParms const & p,
|
||||||
beast::Journal journal)
|
beast::Journal journal)
|
||||||
: lock_(std::make_unique<std::recursive_mutex>())
|
: lock_{std::make_unique<std::recursive_mutex>()}
|
||||||
, clock_(clock)
|
, clock_{clock}
|
||||||
|
, prevRoundTime_{p.ledgerIDLE_INTERVAL}
|
||||||
|
, parms_(p)
|
||||||
, j_{journal}
|
, j_{journal}
|
||||||
{
|
{
|
||||||
JLOG(j_.debug()) << "Creating consensus object";
|
JLOG(j_.debug()) << "Creating consensus object";
|
||||||
@@ -1112,9 +1194,9 @@ Consensus<Derived, Traits>::phaseOpen()
|
|||||||
sinceClose = -duration_cast<milliseconds>(lastCloseTime - now_);
|
sinceClose = -duration_cast<milliseconds>(lastCloseTime - now_);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const idleInterval = std::max<seconds>(
|
auto const idleInterval = std::max<milliseconds>(
|
||||||
LEDGER_IDLE_INTERVAL,
|
parms_.ledgerIDLE_INTERVAL,
|
||||||
duration_cast<seconds>(2 * previousLedger_.closeTimeResolution()));
|
2 * previousLedger_.closeTimeResolution());
|
||||||
|
|
||||||
// Decide if we should close the ledger
|
// Decide if we should close the ledger
|
||||||
if (shouldCloseLedger(
|
if (shouldCloseLedger(
|
||||||
@@ -1126,6 +1208,7 @@ Consensus<Derived, Traits>::phaseOpen()
|
|||||||
sinceClose,
|
sinceClose,
|
||||||
openTime_.read(),
|
openTime_.read(),
|
||||||
idleInterval,
|
idleInterval,
|
||||||
|
parms_,
|
||||||
j_))
|
j_))
|
||||||
{
|
{
|
||||||
closeLedger();
|
closeLedger();
|
||||||
@@ -1143,10 +1226,10 @@ Consensus<Derived, Traits>::phaseEstablish()
|
|||||||
result_->roundTime.tick(clock_.now());
|
result_->roundTime.tick(clock_.now());
|
||||||
|
|
||||||
convergePercent_ = result_->roundTime.read() * 100 /
|
convergePercent_ = result_->roundTime.read() * 100 /
|
||||||
std::max<milliseconds>(prevRoundTime_, AV_MIN_CONSENSUS_TIME);
|
std::max<milliseconds>(prevRoundTime_, parms_.avMIN_CONSENSUS_TIME);
|
||||||
|
|
||||||
// Give everyone a chance to take an initial position
|
// Give everyone a chance to take an initial position
|
||||||
if (result_->roundTime.read() < LEDGER_MIN_CONSENSUS)
|
if (result_->roundTime.read() < parms_.ledgerMIN_CONSENSUS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
updateOurPositions();
|
updateOurPositions();
|
||||||
@@ -1230,8 +1313,8 @@ Consensus<Derived, Traits>::updateOurPositions()
|
|||||||
assert(result_);
|
assert(result_);
|
||||||
|
|
||||||
// Compute a cutoff time
|
// Compute a cutoff time
|
||||||
auto const peerCutoff = now_ - PROPOSE_FRESHNESS;
|
auto const peerCutoff = now_ - parms_.proposeFRESHNESS;
|
||||||
auto const ourCutoff = now_ - PROPOSE_INTERVAL;
|
auto const ourCutoff = now_ - parms_.proposeINTERVAL;
|
||||||
|
|
||||||
// Verify freshness of peer positions and compute close times
|
// Verify freshness of peer positions and compute close times
|
||||||
std::map<NetClock::time_point, int> effCloseTimes;
|
std::map<NetClock::time_point, int> effCloseTimes;
|
||||||
@@ -1271,7 +1354,7 @@ Consensus<Derived, Traits>::updateOurPositions()
|
|||||||
// Because the threshold for inclusion increases,
|
// Because the threshold for inclusion increases,
|
||||||
// time can change our position on a dispute
|
// time can change our position on a dispute
|
||||||
if (it.second.updateVote(
|
if (it.second.updateVote(
|
||||||
convergePercent_, (mode_ == Mode::proposing)))
|
convergePercent_, (mode_ == Mode::proposing), parms_))
|
||||||
{
|
{
|
||||||
if (!mutableSet)
|
if (!mutableSet)
|
||||||
mutableSet.emplace(result_->set);
|
mutableSet.emplace(result_->set);
|
||||||
@@ -1309,14 +1392,14 @@ Consensus<Derived, Traits>::updateOurPositions()
|
|||||||
{
|
{
|
||||||
int neededWeight;
|
int neededWeight;
|
||||||
|
|
||||||
if (convergePercent_ < AV_MID_CONSENSUS_TIME)
|
if (convergePercent_ < parms_.avMID_CONSENSUS_TIME)
|
||||||
neededWeight = AV_INIT_CONSENSUS_PCT;
|
neededWeight = parms_.avINIT_CONSENSUS_PCT;
|
||||||
else if (convergePercent_ < AV_LATE_CONSENSUS_TIME)
|
else if (convergePercent_ < parms_.avLATE_CONSENSUS_TIME)
|
||||||
neededWeight = AV_MID_CONSENSUS_PCT;
|
neededWeight = parms_.avMID_CONSENSUS_PCT;
|
||||||
else if (convergePercent_ < AV_STUCK_CONSENSUS_TIME)
|
else if (convergePercent_ < parms_.avSTUCK_CONSENSUS_TIME)
|
||||||
neededWeight = AV_LATE_CONSENSUS_PCT;
|
neededWeight = parms_.avLATE_CONSENSUS_PCT;
|
||||||
else
|
else
|
||||||
neededWeight = AV_STUCK_CONSENSUS_PCT;
|
neededWeight = parms_.avSTUCK_CONSENSUS_PCT;
|
||||||
|
|
||||||
int participants = peerProposals_.size();
|
int participants = peerProposals_.size();
|
||||||
if (mode_ == Mode::proposing)
|
if (mode_ == Mode::proposing)
|
||||||
@@ -1333,7 +1416,7 @@ Consensus<Derived, Traits>::updateOurPositions()
|
|||||||
|
|
||||||
// Threshold to declare consensus
|
// Threshold to declare consensus
|
||||||
int const threshConsensus =
|
int const threshConsensus =
|
||||||
participantsNeeded(participants, AV_CT_CONSENSUS_PCT);
|
participantsNeeded(participants, parms_.avCT_CONSENSUS_PCT);
|
||||||
|
|
||||||
JLOG(j_.info()) << "Proposers:" << peerProposals_.size()
|
JLOG(j_.info()) << "Proposers:" << peerProposals_.size()
|
||||||
<< " nw:" << neededWeight << " thrV:" << threshVote
|
<< " nw:" << neededWeight << " thrV:" << threshVote
|
||||||
@@ -1454,6 +1537,7 @@ Consensus<Derived, Traits>::haveConsensus()
|
|||||||
currentFinished,
|
currentFinished,
|
||||||
prevRoundTime_,
|
prevRoundTime_,
|
||||||
result_->roundTime.read(),
|
result_->roundTime.read(),
|
||||||
|
parms_,
|
||||||
mode_ == Mode::proposing,
|
mode_ == Mode::proposing,
|
||||||
j_);
|
j_);
|
||||||
|
|
||||||
|
|||||||
135
src/ripple/consensus/ConsensusParms.h
Normal file
135
src/ripple/consensus/ConsensusParms.h
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012-2017 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_CONSENSUS_CONSENSUS_PARMS_H_INCLUDED
|
||||||
|
#define RIPPLE_CONSENSUS_CONSENSUS_PARMS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
/** Consensus algorithm parameters
|
||||||
|
|
||||||
|
Parameters which control the consensus algorithm. This are not
|
||||||
|
meant to be changed arbitrarily.
|
||||||
|
*/
|
||||||
|
struct ConsensusParms
|
||||||
|
{
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Validation and proposal durations are relative to NetClock times, so use
|
||||||
|
// second resolution
|
||||||
|
/** The duration a validation remains current after its ledger's
|
||||||
|
close time.
|
||||||
|
|
||||||
|
This is a safety to protect against very old validations and the time
|
||||||
|
it takes to adjust the close time accuracy window.
|
||||||
|
*/
|
||||||
|
std::chrono::seconds validationVALID_WALL = 5min;
|
||||||
|
|
||||||
|
/** Duration a validation remains current after first observed.
|
||||||
|
|
||||||
|
The duration a validation remains current after the time we
|
||||||
|
first saw it. This provides faster recovery in very rare cases where the
|
||||||
|
number of validations produced by the network is lower than normal
|
||||||
|
*/
|
||||||
|
std::chrono::seconds validationVALID_LOCAL = 3min;
|
||||||
|
|
||||||
|
/** Duration pre-close in which validations are acceptable.
|
||||||
|
|
||||||
|
The number of seconds before a close time that we consider a validation
|
||||||
|
acceptable. This protects against extreme clock errors
|
||||||
|
*/
|
||||||
|
std::chrono::seconds validationVALID_EARLY = 3min;
|
||||||
|
|
||||||
|
|
||||||
|
//! How long we consider a proposal fresh
|
||||||
|
std::chrono::seconds proposeFRESHNESS = 20s;
|
||||||
|
|
||||||
|
//! How often we force generating a new proposal to keep ours fresh
|
||||||
|
std::chrono::seconds proposeINTERVAL = 12s;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Consensus durations are relative to the internal Consenus clock and use
|
||||||
|
// millisecond resolution.
|
||||||
|
|
||||||
|
//! The percentage threshold above which we can declare consensus.
|
||||||
|
std::size_t minCONSENSUS_PCT = 80;
|
||||||
|
|
||||||
|
//! The duration a ledger may remain idle before closing
|
||||||
|
std::chrono::milliseconds ledgerIDLE_INTERVAL = 15s;
|
||||||
|
|
||||||
|
//! The number of seconds we wait minimum to ensure participation
|
||||||
|
std::chrono::milliseconds ledgerMIN_CONSENSUS = 1950ms;
|
||||||
|
|
||||||
|
//! Minimum number of seconds to wait to ensure others have computed the LCL
|
||||||
|
std::chrono::milliseconds ledgerMIN_CLOSE = 2s;
|
||||||
|
|
||||||
|
//! How often we check state or change positions
|
||||||
|
std::chrono::milliseconds ledgerGRANULARITY = 1s;
|
||||||
|
|
||||||
|
/** The minimum amount of time to consider the previous round
|
||||||
|
to have taken.
|
||||||
|
|
||||||
|
The minimum amount of time to consider the previous round
|
||||||
|
to have taken. This ensures that there is an opportunity
|
||||||
|
for a round at each avalanche threshold even if the
|
||||||
|
previous consensus was very fast. This should be at least
|
||||||
|
twice the interval between proposals (0.7s) divided by
|
||||||
|
the interval between mid and late consensus ([85-50]/100).
|
||||||
|
*/
|
||||||
|
std::chrono::milliseconds avMIN_CONSENSUS_TIME = 5s;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Avalanche tuning
|
||||||
|
// As a function of the percent this round's duration is of the prior round,
|
||||||
|
// we increase the threshold for yes vots to add a tranasaction to our
|
||||||
|
// position.
|
||||||
|
|
||||||
|
//! Percentage of nodes on our UNL that must vote yes
|
||||||
|
std::size_t avINIT_CONSENSUS_PCT = 50;
|
||||||
|
|
||||||
|
//! Percentage of previous round duration before we advance
|
||||||
|
std::size_t avMID_CONSENSUS_TIME = 50;
|
||||||
|
|
||||||
|
//! Percentage of nodes that most vote yes after advancing
|
||||||
|
std::size_t avMID_CONSENSUS_PCT = 65;
|
||||||
|
|
||||||
|
//! Percentage of previous round duration before we advance
|
||||||
|
std::size_t avLATE_CONSENSUS_TIME = 85;
|
||||||
|
|
||||||
|
//! Percentage of nodes that most vote yes after advancing
|
||||||
|
std::size_t avLATE_CONSENSUS_PCT = 70;
|
||||||
|
|
||||||
|
//! Percentage of previous round duration before we are stuck
|
||||||
|
std::size_t avSTUCK_CONSENSUS_TIME = 200;
|
||||||
|
|
||||||
|
//! Percentage of nodes that must vote yes after we are stuck
|
||||||
|
std::size_t avSTUCK_CONSENSUS_PCT = 95;
|
||||||
|
|
||||||
|
//! Percentage of nodes required to reach agreement on ledger close time
|
||||||
|
std::size_t avCT_CONSENSUS_PCT = 75;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // ripple
|
||||||
|
#endif
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#include <ripple/basics/Log.h>
|
#include <ripple/basics/Log.h>
|
||||||
#include <ripple/basics/base_uint.h>
|
#include <ripple/basics/base_uint.h>
|
||||||
#include <ripple/beast/utility/Journal.h>
|
#include <ripple/beast/utility/Journal.h>
|
||||||
#include <ripple/consensus/LedgerTiming.h>
|
#include <ripple/consensus/ConsensusParms.h>
|
||||||
#include <ripple/protocol/Serializer.h>
|
#include <ripple/protocol/Serializer.h>
|
||||||
#include <ripple/protocol/UintTypes.h>
|
#include <ripple/protocol/UintTypes.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -112,10 +112,11 @@ public:
|
|||||||
@param percentTime Percentage progress through consensus, e.g. 50%
|
@param percentTime Percentage progress through consensus, e.g. 50%
|
||||||
through or 90%.
|
through or 90%.
|
||||||
@param proposing Whether we are proposing to our peers in this round.
|
@param proposing Whether we are proposing to our peers in this round.
|
||||||
|
@param p Consensus parameters controlling thresholds for voting
|
||||||
@return Whether our vote changed
|
@return Whether our vote changed
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
updateVote(int percentTime, bool proposing);
|
updateVote(int percentTime, bool proposing, ConsensusParms const& p);
|
||||||
|
|
||||||
//! JSON representation of dispute, used for debugging
|
//! JSON representation of dispute, used for debugging
|
||||||
Json::Value
|
Json::Value
|
||||||
@@ -190,7 +191,10 @@ DisputedTx<Tx_t, NodeID_t>::unVote(NodeID_t const& peer)
|
|||||||
|
|
||||||
template <class Tx_t, class NodeID_t>
|
template <class Tx_t, class NodeID_t>
|
||||||
bool
|
bool
|
||||||
DisputedTx<Tx_t, NodeID_t>::updateVote(int percentTime, bool proposing)
|
DisputedTx<Tx_t, NodeID_t>::updateVote(
|
||||||
|
int percentTime,
|
||||||
|
bool proposing,
|
||||||
|
ConsensusParms const& p)
|
||||||
{
|
{
|
||||||
if (ourVote_ && (nays_ == 0))
|
if (ourVote_ && (nays_ == 0))
|
||||||
return false;
|
return false;
|
||||||
@@ -212,14 +216,14 @@ DisputedTx<Tx_t, NodeID_t>::updateVote(int percentTime, bool proposing)
|
|||||||
//
|
//
|
||||||
// To prevent avalanche stalls, we increase the needed weight slightly
|
// To prevent avalanche stalls, we increase the needed weight slightly
|
||||||
// over time.
|
// over time.
|
||||||
if (percentTime < AV_MID_CONSENSUS_TIME)
|
if (percentTime < p.avMID_CONSENSUS_TIME)
|
||||||
newPosition = weight > AV_INIT_CONSENSUS_PCT;
|
newPosition = weight > p.avINIT_CONSENSUS_PCT;
|
||||||
else if (percentTime < AV_LATE_CONSENSUS_TIME)
|
else if (percentTime < p.avLATE_CONSENSUS_TIME)
|
||||||
newPosition = weight > AV_MID_CONSENSUS_PCT;
|
newPosition = weight > p.avMID_CONSENSUS_PCT;
|
||||||
else if (percentTime < AV_STUCK_CONSENSUS_TIME)
|
else if (percentTime < p.avSTUCK_CONSENSUS_TIME)
|
||||||
newPosition = weight > AV_LATE_CONSENSUS_PCT;
|
newPosition = weight > p.avLATE_CONSENSUS_PCT;
|
||||||
else
|
else
|
||||||
newPosition = weight > AV_STUCK_CONSENSUS_PCT;
|
newPosition = weight > p.avSTUCK_CONSENSUS_PCT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,15 +27,9 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// These are protocol parameters used to control the behavior of the system and
|
|
||||||
// they should not be changed arbitrarily.
|
|
||||||
|
|
||||||
//! The percentage threshold above which we can declare consensus.
|
|
||||||
auto constexpr minimumConsensusPercentage = 80;
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
/** Possible close time resolutions.
|
|
||||||
|
/** Possible ledger close time resolutions.
|
||||||
|
|
||||||
Values should not be duplicated.
|
Values should not be duplicated.
|
||||||
@see getNextLedgerTimeResolution
|
@see getNextLedgerTimeResolution
|
||||||
@@ -52,61 +46,6 @@ auto constexpr increaseLedgerTimeResolutionEvery = 8;
|
|||||||
//! How often we decrease the close time resolution (in numbers of ledgers)
|
//! How often we decrease the close time resolution (in numbers of ledgers)
|
||||||
auto constexpr decreaseLedgerTimeResolutionEvery = 1;
|
auto constexpr decreaseLedgerTimeResolutionEvery = 1;
|
||||||
|
|
||||||
//! The number of seconds a ledger may remain idle before closing
|
|
||||||
auto constexpr LEDGER_IDLE_INTERVAL = 15s;
|
|
||||||
|
|
||||||
//! The number of seconds we wait minimum to ensure participation
|
|
||||||
auto constexpr LEDGER_MIN_CONSENSUS = 1950ms;
|
|
||||||
|
|
||||||
//! Minimum number of seconds to wait to ensure others have computed the LCL
|
|
||||||
auto constexpr LEDGER_MIN_CLOSE = 2s;
|
|
||||||
|
|
||||||
//! How often we check state or change positions
|
|
||||||
auto constexpr LEDGER_GRANULARITY = 1s;
|
|
||||||
|
|
||||||
//! How long we consider a proposal fresh
|
|
||||||
auto constexpr PROPOSE_FRESHNESS = 20s;
|
|
||||||
|
|
||||||
//! How often we force generating a new proposal to keep ours fresh
|
|
||||||
auto constexpr PROPOSE_INTERVAL = 12s;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Avalanche tuning
|
|
||||||
//! Percentage of nodes on our UNL that must vote yes
|
|
||||||
auto constexpr AV_INIT_CONSENSUS_PCT = 50;
|
|
||||||
|
|
||||||
//! Percentage of previous close time before we advance
|
|
||||||
auto constexpr AV_MID_CONSENSUS_TIME = 50;
|
|
||||||
|
|
||||||
//! Percentage of nodes that most vote yes after advancing
|
|
||||||
auto constexpr AV_MID_CONSENSUS_PCT = 65;
|
|
||||||
|
|
||||||
//! Percentage of previous close time before we advance
|
|
||||||
auto constexpr AV_LATE_CONSENSUS_TIME = 85;
|
|
||||||
|
|
||||||
//! Percentage of nodes that most vote yes after advancing
|
|
||||||
auto constexpr AV_LATE_CONSENSUS_PCT = 70;
|
|
||||||
|
|
||||||
//! Percentage of previous close time before we are stuck
|
|
||||||
auto constexpr AV_STUCK_CONSENSUS_TIME = 200;
|
|
||||||
|
|
||||||
//! Percentage of nodes that must vote yes after we are stuck
|
|
||||||
auto constexpr AV_STUCK_CONSENSUS_PCT = 95;
|
|
||||||
|
|
||||||
//! Percentage of nodes required to reach agreement on ledger close time
|
|
||||||
auto constexpr AV_CT_CONSENSUS_PCT = 75;
|
|
||||||
|
|
||||||
/** The minimum amount of time to consider the previous round
|
|
||||||
to have taken.
|
|
||||||
|
|
||||||
The minimum amount of time to consider the previous round
|
|
||||||
to have taken. This ensures that there is an opportunity
|
|
||||||
for a round at each avalanche threshold even if the
|
|
||||||
previous consensus was very fast. This should be at least
|
|
||||||
twice the interval between proposals (0.7s) divided by
|
|
||||||
the interval between mid and late consensus ([85-50]/100).
|
|
||||||
*/
|
|
||||||
auto constexpr AV_MIN_CONSENSUS_TIME = 5s;
|
|
||||||
|
|
||||||
/** Calculates the close time resolution for the specified ledger.
|
/** Calculates the close time resolution for the specified ledger.
|
||||||
|
|
||||||
@@ -200,6 +139,8 @@ effCloseTime(
|
|||||||
typename time_point::duration const resolution,
|
typename time_point::duration const resolution,
|
||||||
time_point priorCloseTime)
|
time_point priorCloseTime)
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
if (closeTime == time_point{})
|
if (closeTime == time_point{})
|
||||||
return closeTime;
|
return closeTime;
|
||||||
|
|
||||||
@@ -207,78 +148,5 @@ effCloseTime(
|
|||||||
roundCloseTime(closeTime, resolution), (priorCloseTime + 1s));
|
roundCloseTime(closeTime, resolution), (priorCloseTime + 1s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 prevProposers 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 prevRoundTime time for the previous ledger to reach consensus
|
|
||||||
@param timeSincePrevClose time since the previous ledger's (possibly rounded)
|
|
||||||
close time
|
|
||||||
@param openTime duration this ledger has been open
|
|
||||||
@param idleInterval the network's desired idle interval
|
|
||||||
@param j journal for logging
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
shouldCloseLedger(
|
|
||||||
bool anyTransactions,
|
|
||||||
std::size_t prevProposers,
|
|
||||||
std::size_t proposersClosed,
|
|
||||||
std::size_t proposersValidated,
|
|
||||||
std::chrono::milliseconds prevRoundTime,
|
|
||||||
std::chrono::milliseconds timeSincePrevClose,
|
|
||||||
std::chrono::milliseconds openTime,
|
|
||||||
std::chrono::seconds idleInterval,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
/** Determine if a consensus has been reached
|
|
||||||
|
|
||||||
This function determines if a consensus has been reached
|
|
||||||
|
|
||||||
@param agreeing count of agreements with our position
|
|
||||||
@param total count of participants other than us
|
|
||||||
@param count_self whether we count ourselves
|
|
||||||
@return True if a consensus has been reached
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
checkConsensusReached(std::size_t agreeing, std::size_t total, bool count_self);
|
|
||||||
|
|
||||||
/** Whether we have or don't have a consensus */
|
|
||||||
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 prevProposers 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
|
|
||||||
@param proposing whether we should count ourselves
|
|
||||||
@param j journal for logging
|
|
||||||
*/
|
|
||||||
ConsensusState
|
|
||||||
checkConsensus(
|
|
||||||
std::size_t prevProposers,
|
|
||||||
std::size_t currentProposers,
|
|
||||||
std::size_t currentAgree,
|
|
||||||
std::size_t currentFinished,
|
|
||||||
std::chrono::milliseconds previousAgreeTime,
|
|
||||||
std::chrono::milliseconds currentAgreeTime,
|
|
||||||
bool proposing,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
} // ripple
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,4 +18,4 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
#include <BeastConfig.h>
|
#include <BeastConfig.h>
|
||||||
|
|
||||||
#include <ripple/consensus/LedgerTiming.cpp>
|
#include <ripple/consensus/Consensus.cpp>
|
||||||
|
|||||||
@@ -31,13 +31,97 @@ namespace test {
|
|||||||
class Consensus_test : public beast::unit_test::suite
|
class Consensus_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void
|
||||||
|
testShouldCloseLedger()
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
// Use default parameters
|
||||||
|
ConsensusParms p;
|
||||||
|
beast::Journal j;
|
||||||
|
|
||||||
|
// Bizarre times forcibly close
|
||||||
|
BEAST_EXPECT(
|
||||||
|
shouldCloseLedger(true, 10, 10, 10, -10s, 10s, 1s, 1s, p, j));
|
||||||
|
BEAST_EXPECT(
|
||||||
|
shouldCloseLedger(true, 10, 10, 10, 100h, 10s, 1s, 1s, p, j));
|
||||||
|
BEAST_EXPECT(
|
||||||
|
shouldCloseLedger(true, 10, 10, 10, 10s, 100h, 1s, 1s, p, j));
|
||||||
|
|
||||||
|
// Rest of network has closed
|
||||||
|
BEAST_EXPECT(
|
||||||
|
shouldCloseLedger(true, 10, 3, 5, 10s, 10s, 10s, 10s, p, j));
|
||||||
|
|
||||||
|
// No transactions means wait until end of internval
|
||||||
|
BEAST_EXPECT(
|
||||||
|
!shouldCloseLedger(false, 10, 0, 0, 1s, 1s, 1s, 10s, p, j));
|
||||||
|
BEAST_EXPECT(
|
||||||
|
shouldCloseLedger(false, 10, 0, 0, 1s, 10s, 1s, 10s, p, j));
|
||||||
|
|
||||||
|
// Enforce minimum ledger open time
|
||||||
|
BEAST_EXPECT(
|
||||||
|
!shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 1s, 10s, p, j));
|
||||||
|
|
||||||
|
// Don't go too much faster than last time
|
||||||
|
BEAST_EXPECT(
|
||||||
|
!shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 3s, 10s, p, j));
|
||||||
|
|
||||||
|
BEAST_EXPECT(
|
||||||
|
shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 10s, 10s, p, j));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testCheckConsensus()
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
// Use default parameterss
|
||||||
|
ConsensusParms p;
|
||||||
|
beast::Journal j;
|
||||||
|
|
||||||
|
|
||||||
|
// Not enough time has elapsed
|
||||||
|
BEAST_EXPECT(
|
||||||
|
ConsensusState::No ==
|
||||||
|
checkConsensus(10, 2, 2, 0, 3s, 2s, p, true, j));
|
||||||
|
|
||||||
|
// If not enough peers have propsed, ensure
|
||||||
|
// more time for proposals
|
||||||
|
BEAST_EXPECT(
|
||||||
|
ConsensusState::No ==
|
||||||
|
checkConsensus(10, 2, 2, 0, 3s, 4s, p, true, j));
|
||||||
|
|
||||||
|
// Enough time has elapsed and we all agree
|
||||||
|
BEAST_EXPECT(
|
||||||
|
ConsensusState::Yes ==
|
||||||
|
checkConsensus(10, 2, 2, 0, 3s, 10s, p, true, j));
|
||||||
|
|
||||||
|
// Enough time has elapsed and we don't yet agree
|
||||||
|
BEAST_EXPECT(
|
||||||
|
ConsensusState::No ==
|
||||||
|
checkConsensus(10, 2, 1, 0, 3s, 10s, p, true, j));
|
||||||
|
|
||||||
|
// Our peers have moved on
|
||||||
|
// Enough time has elapsed and we all agree
|
||||||
|
BEAST_EXPECT(
|
||||||
|
ConsensusState::MovedOn ==
|
||||||
|
checkConsensus(10, 2, 1, 8, 3s, 10s, p, true, j));
|
||||||
|
|
||||||
|
// No peers makes it easy to agree
|
||||||
|
BEAST_EXPECT(
|
||||||
|
ConsensusState::Yes ==
|
||||||
|
checkConsensus(0, 0, 0, 0, 3s, 10s, p, true, j));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testStandalone()
|
testStandalone()
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
using namespace csf;
|
using namespace csf;
|
||||||
|
|
||||||
|
ConsensusParms parms;
|
||||||
auto tg = TrustGraph::makeComplete(1);
|
auto tg = TrustGraph::makeComplete(1);
|
||||||
Sim s(tg, topology(tg, fixed{LEDGER_GRANULARITY}));
|
Sim s(parms, tg, topology(tg, fixed{parms.ledgerGRANULARITY}));
|
||||||
|
|
||||||
auto& p = s.peers[0];
|
auto& p = s.peers[0];
|
||||||
|
|
||||||
@@ -63,10 +147,14 @@ public:
|
|||||||
using namespace csf;
|
using namespace csf;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
ConsensusParms parms;
|
||||||
auto tg = TrustGraph::makeComplete(5);
|
auto tg = TrustGraph::makeComplete(5);
|
||||||
Sim sim(
|
Sim sim(
|
||||||
|
parms,
|
||||||
tg,
|
tg,
|
||||||
topology(tg, fixed{round<milliseconds>(0.2 * LEDGER_GRANULARITY)}));
|
topology(
|
||||||
|
tg,
|
||||||
|
fixed{round<milliseconds>(0.2 * parms.ledgerGRANULARITY)}));
|
||||||
|
|
||||||
// everyone submits their own ID as a TX and relay it to peers
|
// everyone submits their own ID as a TX and relay it to peers
|
||||||
for (auto& p : sim.peers)
|
for (auto& p : sim.peers)
|
||||||
@@ -98,12 +186,13 @@ public:
|
|||||||
|
|
||||||
for (auto isParticipant : {true, false})
|
for (auto isParticipant : {true, false})
|
||||||
{
|
{
|
||||||
|
ConsensusParms parms;
|
||||||
auto tg = TrustGraph::makeComplete(5);
|
auto tg = TrustGraph::makeComplete(5);
|
||||||
|
|
||||||
Sim sim(tg, topology(tg, [](PeerID i, PeerID j) {
|
Sim sim(parms, tg, topology(tg, [&](PeerID i, PeerID j) {
|
||||||
auto delayFactor = (i == 0 || j == 0) ? 1.1 : 0.2;
|
auto delayFactor = (i == 0 || j == 0) ? 1.1 : 0.2;
|
||||||
return round<milliseconds>(
|
return round<milliseconds>(
|
||||||
delayFactor * LEDGER_GRANULARITY);
|
delayFactor * parms.ledgerGRANULARITY);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
sim.peers[0].proposing_ = sim.peers[0].validating_ = isParticipant;
|
sim.peers[0].proposing_ = sim.peers[0].validating_ = isParticipant;
|
||||||
@@ -183,7 +272,7 @@ public:
|
|||||||
// the skews need to be at least 10 seconds.
|
// the skews need to be at least 10 seconds.
|
||||||
|
|
||||||
// Complicating this matter is that nodes will ignore proposals
|
// Complicating this matter is that nodes will ignore proposals
|
||||||
// with times more than PROPOSE_FRESHNESS =20s in the past. So at
|
// with times more than proposeFRESHNESS =20s in the past. So at
|
||||||
// the minimum granularity, we have at most 3 types of skews
|
// the minimum granularity, we have at most 3 types of skews
|
||||||
// (0s,10s,20s).
|
// (0s,10s,20s).
|
||||||
|
|
||||||
@@ -191,22 +280,26 @@ public:
|
|||||||
// skew. Then no majority (1/3 < 1/2) of nodes will agree on an
|
// skew. Then no majority (1/3 < 1/2) of nodes will agree on an
|
||||||
// actual close time.
|
// actual close time.
|
||||||
|
|
||||||
|
ConsensusParms parms;
|
||||||
auto tg = TrustGraph::makeComplete(6);
|
auto tg = TrustGraph::makeComplete(6);
|
||||||
Sim sim(
|
Sim sim(
|
||||||
|
parms,
|
||||||
tg,
|
tg,
|
||||||
topology(tg, fixed{round<milliseconds>(0.2 * LEDGER_GRANULARITY)}));
|
topology(
|
||||||
|
tg,
|
||||||
|
fixed{round<milliseconds>(0.2 * parms.ledgerGRANULARITY)}));
|
||||||
|
|
||||||
// Run consensus without skew until we have a short close time
|
// Run consensus without skew until we have a short close time
|
||||||
// resolution
|
// resolution
|
||||||
while (sim.peers.front().lastClosedLedger.closeTimeResolution() >=
|
while (sim.peers.front().lastClosedLedger.closeTimeResolution() >=
|
||||||
PROPOSE_FRESHNESS)
|
parms.proposeFRESHNESS)
|
||||||
sim.run(1);
|
sim.run(1);
|
||||||
|
|
||||||
// Introduce a shift on the time of half the peers
|
// Introduce a shift on the time of half the peers
|
||||||
sim.peers[0].clockSkew = PROPOSE_FRESHNESS / 2;
|
sim.peers[0].clockSkew = parms.proposeFRESHNESS / 2;
|
||||||
sim.peers[1].clockSkew = PROPOSE_FRESHNESS / 2;
|
sim.peers[1].clockSkew = parms.proposeFRESHNESS / 2;
|
||||||
sim.peers[2].clockSkew = PROPOSE_FRESHNESS;
|
sim.peers[2].clockSkew = parms.proposeFRESHNESS;
|
||||||
sim.peers[3].clockSkew = PROPOSE_FRESHNESS;
|
sim.peers[3].clockSkew = parms.proposeFRESHNESS;
|
||||||
|
|
||||||
// Verify all peers have the same LCL and it has all the Txs
|
// Verify all peers have the same LCL and it has all the Txs
|
||||||
sim.run(1);
|
sim.run(1);
|
||||||
@@ -224,9 +317,12 @@ public:
|
|||||||
// Specialized test to exercise a temporary fork in which some peers
|
// Specialized test to exercise a temporary fork in which some peers
|
||||||
// are working on an incorrect prior ledger.
|
// are working on an incorrect prior ledger.
|
||||||
|
|
||||||
|
ConsensusParms parms;
|
||||||
|
|
||||||
|
|
||||||
// Vary the time it takes to process validations to exercise detecting
|
// Vary the time it takes to process validations to exercise detecting
|
||||||
// the wrong LCL at different phases of consensus
|
// the wrong LCL at different phases of consensus
|
||||||
for (auto validationDelay : {0s, LEDGER_MIN_CLOSE})
|
for (auto validationDelay : {0ms, parms.ledgerMIN_CLOSE})
|
||||||
{
|
{
|
||||||
// Consider 10 peers:
|
// Consider 10 peers:
|
||||||
// 0 1 2 3 4 5 6 7 8 9
|
// 0 1 2 3 4 5 6 7 8 9
|
||||||
@@ -256,10 +352,10 @@ public:
|
|||||||
|
|
||||||
// This topology can fork, which is why we are using it for this
|
// This topology can fork, which is why we are using it for this
|
||||||
// test.
|
// test.
|
||||||
BEAST_EXPECT(tg.canFork(minimumConsensusPercentage / 100.));
|
BEAST_EXPECT(tg.canFork(parms.minCONSENSUS_PCT / 100.));
|
||||||
|
|
||||||
auto netDelay = round<milliseconds>(0.2 * LEDGER_GRANULARITY);
|
auto netDelay = round<milliseconds>(0.2 * parms.ledgerGRANULARITY);
|
||||||
Sim sim(tg, topology(tg, fixed{netDelay}));
|
Sim sim(parms, tg, topology(tg, fixed{netDelay}));
|
||||||
|
|
||||||
// initial round to set prior state
|
// initial round to set prior state
|
||||||
sim.run(1);
|
sim.run(1);
|
||||||
@@ -283,7 +379,7 @@ public:
|
|||||||
// wrong ones) and recover within that round since wrong LCL
|
// wrong ones) and recover within that round since wrong LCL
|
||||||
// is detected before we close
|
// is detected before we close
|
||||||
//
|
//
|
||||||
// With a validation delay of LEDGER_MIN_CLOSE, we need 3 more
|
// With a validation delay of ledgerMIN_CLOSE, we need 3 more
|
||||||
// rounds.
|
// rounds.
|
||||||
// 1. Round to generate different ledgers
|
// 1. Round to generate different ledgers
|
||||||
// 2. Round to detect different prior ledgers (but still generate
|
// 2. Round to detect different prior ledgers (but still generate
|
||||||
@@ -324,9 +420,6 @@ public:
|
|||||||
// switchLCL switched from establish to open phase, but still processed
|
// switchLCL switched from establish to open phase, but still processed
|
||||||
// the establish phase logic.
|
// the establish phase logic.
|
||||||
{
|
{
|
||||||
using namespace csf;
|
|
||||||
using namespace std::chrono;
|
|
||||||
|
|
||||||
// A mostly disjoint topology
|
// A mostly disjoint topology
|
||||||
std::vector<UNL> unls;
|
std::vector<UNL> unls;
|
||||||
unls.push_back({0, 1});
|
unls.push_back({0, 1});
|
||||||
@@ -337,14 +430,14 @@ public:
|
|||||||
|
|
||||||
TrustGraph tg{unls, membership};
|
TrustGraph tg{unls, membership};
|
||||||
|
|
||||||
Sim sim(tg, topology(tg, fixed{round<milliseconds>(
|
Sim sim(parms, tg, topology(tg, fixed{round<milliseconds>(
|
||||||
0.2 * LEDGER_GRANULARITY)}));
|
0.2 * parms.ledgerGRANULARITY)}));
|
||||||
|
|
||||||
// initial ground to set prior state
|
// initial ground to set prior state
|
||||||
sim.run(1);
|
sim.run(1);
|
||||||
for (auto &p : sim.peers) {
|
for (auto &p : sim.peers) {
|
||||||
// A long delay to acquire a missing ledger from the network
|
// A long delay to acquire a missing ledger from the network
|
||||||
p.missingLedgerDelay = 2 * LEDGER_MIN_CLOSE;
|
p.missingLedgerDelay = 2 * parms.ledgerMIN_CLOSE;
|
||||||
|
|
||||||
// Everyone sees only their own LCL
|
// Everyone sees only their own LCL
|
||||||
p.openTxs.insert(Tx(p.id));
|
p.openTxs.insert(Tx(p.id));
|
||||||
@@ -367,11 +460,15 @@ public:
|
|||||||
int numPeers = 10;
|
int numPeers = 10;
|
||||||
for (int overlap = 0; overlap <= numPeers; ++overlap)
|
for (int overlap = 0; overlap <= numPeers; ++overlap)
|
||||||
{
|
{
|
||||||
|
ConsensusParms parms;
|
||||||
auto tg = TrustGraph::makeClique(numPeers, overlap);
|
auto tg = TrustGraph::makeClique(numPeers, overlap);
|
||||||
Sim sim(
|
Sim sim(
|
||||||
|
parms,
|
||||||
tg,
|
tg,
|
||||||
topology(
|
topology(
|
||||||
tg, fixed{round<milliseconds>(0.2 * LEDGER_GRANULARITY)}));
|
tg,
|
||||||
|
fixed{
|
||||||
|
round<milliseconds>(0.2 * parms.ledgerGRANULARITY)}));
|
||||||
|
|
||||||
// Initial round to set prior state
|
// Initial round to set prior state
|
||||||
sim.run(1);
|
sim.run(1);
|
||||||
@@ -406,7 +503,7 @@ public:
|
|||||||
simClockSkew()
|
simClockSkew()
|
||||||
{
|
{
|
||||||
using namespace csf;
|
using namespace csf;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
// Attempting to test what happens if peers enter consensus well
|
// Attempting to test what happens if peers enter consensus well
|
||||||
// separated in time. Initial round (in which peers are not staggered)
|
// separated in time. Initial round (in which peers are not staggered)
|
||||||
// is used to get the network going, then transactions are submitted
|
// is used to get the network going, then transactions are submitted
|
||||||
@@ -422,8 +519,9 @@ public:
|
|||||||
|
|
||||||
for (auto stagger : {800ms, 1600ms, 3200ms, 30000ms, 45000ms, 300000ms})
|
for (auto stagger : {800ms, 1600ms, 3200ms, 30000ms, 45000ms, 300000ms})
|
||||||
{
|
{
|
||||||
|
ConsensusParms parms;
|
||||||
auto tg = TrustGraph::makeComplete(5);
|
auto tg = TrustGraph::makeComplete(5);
|
||||||
Sim sim(tg, topology(tg, [](PeerID i, PeerID) {
|
Sim sim(parms, tg, topology(tg, [](PeerID i, PeerID) {
|
||||||
return 200ms * (i + 1);
|
return 200ms * (i + 1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -474,6 +572,7 @@ public:
|
|||||||
double transProb = 0.5;
|
double transProb = 0.5;
|
||||||
|
|
||||||
std::mt19937_64 rng;
|
std::mt19937_64 rng;
|
||||||
|
ConsensusParms parms;
|
||||||
|
|
||||||
auto tg = TrustGraph::makeRandomRanked(
|
auto tg = TrustGraph::makeRandomRanked(
|
||||||
N,
|
N,
|
||||||
@@ -483,8 +582,11 @@ public:
|
|||||||
rng);
|
rng);
|
||||||
|
|
||||||
Sim sim{
|
Sim sim{
|
||||||
|
parms,
|
||||||
tg,
|
tg,
|
||||||
topology(tg, fixed{round<milliseconds>(0.2 * LEDGER_GRANULARITY)})};
|
topology(
|
||||||
|
tg,
|
||||||
|
fixed{round<milliseconds>(0.2 * parms.ledgerGRANULARITY)})};
|
||||||
|
|
||||||
// Initial round to set prior state
|
// Initial round to set prior state
|
||||||
sim.run(1);
|
sim.run(1);
|
||||||
@@ -511,6 +613,9 @@ public:
|
|||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
|
testShouldCloseLedger();
|
||||||
|
testCheckConsensus();
|
||||||
|
|
||||||
testStandalone();
|
testStandalone();
|
||||||
testPeersAgree();
|
testPeersAgree();
|
||||||
testSlowPeer();
|
testSlowPeer();
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class LedgerTiming_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
void testRoundCloseTime()
|
void testRoundCloseTime()
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
// A closeTime equal to the epoch is not modified
|
// A closeTime equal to the epoch is not modified
|
||||||
using tp = NetClock::time_point;
|
using tp = NetClock::time_point;
|
||||||
tp def;
|
tp def;
|
||||||
@@ -94,67 +95,11 @@ class LedgerTiming_test : public beast::unit_test::suite
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testShouldCloseLedger()
|
|
||||||
{
|
|
||||||
// Bizarre times forcibly close
|
|
||||||
BEAST_EXPECT(shouldCloseLedger(true, 10, 10, 10, -10s, 10s, 1s, 1s, j));
|
|
||||||
BEAST_EXPECT(shouldCloseLedger(true, 10, 10, 10, 100h, 10s, 1s, 1s, j));
|
|
||||||
BEAST_EXPECT(shouldCloseLedger(true, 10, 10, 10, 10s, 100h, 1s, 1s, j));
|
|
||||||
|
|
||||||
// Rest of network has closed
|
|
||||||
BEAST_EXPECT(shouldCloseLedger(true, 10, 3, 5, 10s, 10s, 10s, 10s, j));
|
|
||||||
|
|
||||||
// No transactions means wait until end of internval
|
|
||||||
BEAST_EXPECT(!shouldCloseLedger(false, 10, 0, 0, 1s, 1s, 1s, 10s, j));
|
|
||||||
BEAST_EXPECT(shouldCloseLedger(false, 10, 0, 0, 1s, 10s, 1s, 10s, j));
|
|
||||||
|
|
||||||
// Enforce minimum ledger open time
|
|
||||||
BEAST_EXPECT(!shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 1s, 10s, j));
|
|
||||||
|
|
||||||
// Don't go too much faster than last time
|
|
||||||
BEAST_EXPECT(!shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 3s, 10s, j));
|
|
||||||
|
|
||||||
BEAST_EXPECT(shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 10s, 10s, j));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void testCheckConsensus()
|
|
||||||
{
|
|
||||||
// Not enough time has elapsed
|
|
||||||
BEAST_EXPECT( ConsensusState::No
|
|
||||||
== checkConsensus(10, 2, 2, 0, 3s, 2s, true, j));
|
|
||||||
|
|
||||||
// If not enough peers have propsed, ensure
|
|
||||||
// more time for proposals
|
|
||||||
BEAST_EXPECT( ConsensusState::No
|
|
||||||
== checkConsensus(10, 2, 2, 0, 3s, 4s, true, j));
|
|
||||||
|
|
||||||
// Enough time has elapsed and we all agree
|
|
||||||
BEAST_EXPECT( ConsensusState::Yes
|
|
||||||
== checkConsensus(10, 2, 2, 0, 3s, 10s, true, j));
|
|
||||||
|
|
||||||
// Enough time has elapsed and we don't yet agree
|
|
||||||
BEAST_EXPECT( ConsensusState::No
|
|
||||||
== checkConsensus(10, 2, 1, 0, 3s, 10s, true, j));
|
|
||||||
|
|
||||||
// Our peers have moved on
|
|
||||||
// Enough time has elapsed and we all agree
|
|
||||||
BEAST_EXPECT( ConsensusState::MovedOn
|
|
||||||
== checkConsensus(10, 2, 1, 8, 3s, 10s, true, j));
|
|
||||||
|
|
||||||
// No peers makes it easy to agree
|
|
||||||
BEAST_EXPECT( ConsensusState::Yes
|
|
||||||
== checkConsensus(0, 0, 0, 0, 3s, 10s, true, j));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
testGetNextLedgerTimeResolution();
|
testGetNextLedgerTimeResolution();
|
||||||
testRoundCloseTime();
|
testRoundCloseTime();
|
||||||
testShouldCloseLedger();
|
|
||||||
testCheckConsensus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#define RIPPLE_TEST_CSF_LEDGER_H_INCLUDED
|
#define RIPPLE_TEST_CSF_LEDGER_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/basics/chrono.h>
|
#include <ripple/basics/chrono.h>
|
||||||
|
#include <ripple/consensus/LedgerTiming.h>
|
||||||
#include <test/csf/Tx.h>
|
#include <test/csf/Tx.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|||||||
@@ -173,8 +173,8 @@ struct Peer : public Consensus<Peer, Traits>
|
|||||||
bool proposing_ = true;
|
bool proposing_ = true;
|
||||||
|
|
||||||
//! All peers start from the default constructed ledger
|
//! All peers start from the default constructed ledger
|
||||||
Peer(PeerID i, BasicNetwork<Peer*>& n, UNL const& u)
|
Peer(PeerID i, BasicNetwork<Peer*>& n, UNL const& u, ConsensusParms p)
|
||||||
: Consensus<Peer, Traits>(n.clock(), beast::Journal{})
|
: Consensus<Peer, Traits>(n.clock(), p, beast::Journal{})
|
||||||
, id{i}
|
, id{i}
|
||||||
, net{n}
|
, net{n}
|
||||||
, unl(u)
|
, unl(u)
|
||||||
@@ -395,12 +395,12 @@ struct Peer : public Consensus<Peer, Traits>
|
|||||||
Base::timerEntry(now());
|
Base::timerEntry(now());
|
||||||
// only reschedule if not completed
|
// only reschedule if not completed
|
||||||
if (completedLedgers < targetLedgers)
|
if (completedLedgers < targetLedgers)
|
||||||
net.timer(LEDGER_GRANULARITY, [&]() { timerEntry(); });
|
net.timer(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
start()
|
start()
|
||||||
{
|
{
|
||||||
net.timer(LEDGER_GRANULARITY, [&]() { timerEntry(); });
|
net.timer(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
|
||||||
// The ID is the one we have seen the most validations for
|
// The ID is the one we have seen the most validations for
|
||||||
// In practice, we might not actually have that ledger itself yet,
|
// In practice, we might not actually have that ledger itself yet,
|
||||||
// so there is no gaurantee that bestLCL == lastClosedLedger.id()
|
// so there is no gaurantee that bestLCL == lastClosedLedger.id()
|
||||||
@@ -415,8 +415,9 @@ struct Peer : public Consensus<Peer, Traits>
|
|||||||
// We don't care about the actual epochs, but do want the
|
// We don't care about the actual epochs, but do want the
|
||||||
// generated NetClock time to be well past its epoch to ensure
|
// generated NetClock time to be well past its epoch to ensure
|
||||||
// any subtractions of two NetClock::time_point in the consensu
|
// any subtractions of two NetClock::time_point in the consensu
|
||||||
// code are positive. (e.g. PROPOSE_FRESHNESS)
|
// code are positive. (e.g. proposeFRESHNESS)
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
return NetClock::time_point(duration_cast<NetClock::duration>(
|
return NetClock::time_point(duration_cast<NetClock::duration>(
|
||||||
net.now().time_since_epoch() + 86400s + clockSkew));
|
net.now().time_since_epoch() + 86400s + clockSkew));
|
||||||
}
|
}
|
||||||
@@ -427,6 +428,8 @@ struct Peer : public Consensus<Peer, Traits>
|
|||||||
void
|
void
|
||||||
schedule(std::chrono::nanoseconds when, T&& what)
|
schedule(std::chrono::nanoseconds when, T&& what)
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
if (when == 0ns)
|
if (when == 0ns)
|
||||||
what();
|
what();
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -47,14 +47,15 @@ public:
|
|||||||
|
|
||||||
@param g The trust graph between peers.
|
@param g The trust graph between peers.
|
||||||
@param top The network topology between peers.
|
@param top The network topology between peers.
|
||||||
|
@param parms Consensus parameters to use in the simulation
|
||||||
|
|
||||||
*/
|
*/
|
||||||
template <class Topology>
|
template <class Topology>
|
||||||
Sim(TrustGraph const& g, Topology const& top)
|
Sim(ConsensusParms parms, TrustGraph const& g, Topology const& top)
|
||||||
{
|
{
|
||||||
peers.reserve(g.numPeers());
|
peers.reserve(g.numPeers());
|
||||||
for (int i = 0; i < g.numPeers(); ++i)
|
for (int i = 0; i < g.numPeers(); ++i)
|
||||||
peers.emplace_back(i, net, g.unl(i));
|
peers.emplace_back(i, net, g.unl(i), parms);
|
||||||
|
|
||||||
for (int i = 0; i < peers.size(); ++i)
|
for (int i = 0; i < peers.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user