Consensus cleanup:

* Inject dependencies, make functions free and levelize
* Add comments to document the intent behind the code
* Reduce class public interfaces
* Remove support for proposals without ledger hashes
This commit is contained in:
Nik Bougalis
2015-05-22 13:08:41 -07:00
committed by Tom Ritchford
parent 1b4e0f5f48
commit dd902292ed
26 changed files with 467 additions and 524 deletions

View File

@@ -1394,26 +1394,44 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\DirectoryEntryIterator.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\DisputedTx.cpp">
<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>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\DisputedTx.h">
<ClInclude Include="..\..\src\ripple\app\ledger\impl\DisputedTx.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedgers.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerCleaner.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\LedgerCleaner.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerConsensus.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<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>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\InboundLedger.cpp">
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerMaster.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerTiming.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedger.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\InboundLedgers.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedgers.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\Ledger.cpp">
@@ -1422,16 +1440,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\Ledger.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerCleaner.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerCleaner.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerConsensus.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerConsensus.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerEntrySet.cpp">
@@ -1450,10 +1458,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerHolder.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerMaster.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerMaster.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerProposal.cpp">
@@ -1462,10 +1466,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerProposal.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerTiming.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerTiming.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerToJson.h">

View File

@@ -2115,24 +2115,39 @@
<ClInclude Include="..\..\src\ripple\app\ledger\DirectoryEntryIterator.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\DisputedTx.cpp">
<Filter>ripple\app\ledger</Filter>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\DisputedTx.h">
<Filter>ripple\app\ledger</Filter>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\DisputedTx.h">
<Filter>ripple\app\ledger\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedger.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedgers.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerCleaner.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<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">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerFees.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\InboundLedger.cpp">
<Filter>ripple\app\ledger</Filter>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerMaster.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerTiming.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedger.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\InboundLedgers.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\InboundLedgers.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
@@ -2142,15 +2157,6 @@
<ClInclude Include="..\..\src\ripple\app\ledger\Ledger.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerCleaner.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerCleaner.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerConsensus.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerConsensus.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
@@ -2172,9 +2178,6 @@
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerHolder.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerMaster.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerMaster.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
@@ -2184,9 +2187,6 @@
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerProposal.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerTiming.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerTiming.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>

View File

@@ -27,7 +27,6 @@
namespace ripple {
// VFALCO TODO Rename to InboundLedger
// A ledger we are trying to acquire
class InboundLedger
: public PeerSet

View File

@@ -1592,16 +1592,6 @@ void Ledger::updateSkipList ()
}
}
std::uint32_t Ledger::roundCloseTime (
std::uint32_t closeTime, std::uint32_t closeResolution)
{
if (closeTime == 0)
return 0;
closeTime += (closeResolution / 2);
return closeTime - (closeTime % closeResolution);
}
/** Save, or arrange to save, a fully-validated ledger
Returns false on error
*/

View File

@@ -139,8 +139,6 @@ public:
~Ledger ();
static Ledger::pointer getLastFullLedger ();
static std::uint32_t roundCloseTime (
std::uint32_t closeTime, std::uint32_t closeResolution);
void updateHash ();
void setClosed ()

View File

@@ -24,6 +24,7 @@
#include <ripple/app/ledger/LedgerProposal.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/app/tx/InboundTransactions.h>
#include <ripple/app/tx/LocalTxs.h>
#include <ripple/json/json_value.h>
#include <ripple/overlay/Peer.h>
@@ -42,8 +43,6 @@ class LedgerConsensus
public:
virtual ~LedgerConsensus() = 0;
virtual int startup () = 0;
virtual Json::Value getJson (bool full) = 0;
virtual uint256 getLCL () = 0;
@@ -55,12 +54,22 @@ public:
virtual bool peerPosition (LedgerProposal::ref) = 0;
// test/debug
/** Simulate the consensus process without any network traffic.
The end result, is that consensus begins and completes as if everyone
had agreed with whatever we propose.
This function is only called from the rpc "ledger_accept" path with the
server in standalone mode and SHOULD NOT be used during the normal
consensus process.
*/
virtual void simulate () = 0;
};
std::shared_ptr <LedgerConsensus>
make_LedgerConsensus (LocalTxs& localtx,
make_LedgerConsensus (
int previousProposers, int previousConvergeTime,
InboundTransactions& inboundTransactions, LocalTxs& localtx,
LedgerHash const & prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote);

View File

@@ -26,34 +26,38 @@
namespace ripple {
LedgerProposal::LedgerProposal (uint256 const& pLgr, std::uint32_t seq,
uint256 const& tx, std::uint32_t closeTime,
RippleAddress const& naPeerPublic, uint256 const& suppression) :
mPreviousLedger (pLgr), mCurrentHash (tx), mSuppression (suppression), mCloseTime (closeTime),
mProposeSeq (seq), mPublicKey (naPeerPublic)
{
// XXX Validate key.
// if (!mKey->SetPubKey(pubKey))
// throw std::runtime_error("Invalid public key in proposal");
mPeerID = mPublicKey.getNodeID ();
mTime = std::chrono::steady_clock::now ();
}
LedgerProposal::LedgerProposal (RippleAddress const& naPub, RippleAddress const& naPriv,
uint256 const& prevLgr, uint256 const& position,
std::uint32_t closeTime) :
mPreviousLedger (prevLgr), mCurrentHash (position), mCloseTime (closeTime), mProposeSeq (0),
mPublicKey (naPub), mPrivateKey (naPriv)
LedgerProposal::LedgerProposal (
uint256 const& pLgr,
std::uint32_t seq,
uint256 const& tx,
std::uint32_t closeTime,
RippleAddress const& publicKey,
uint256 const& suppression)
: mPreviousLedger (pLgr)
, mCurrentHash (tx)
, mSuppression (suppression)
, mCloseTime (closeTime)
, mProposeSeq (seq)
, mPublicKey (publicKey)
{
mPeerID = mPublicKey.getNodeID ();
mTime = std::chrono::steady_clock::now ();
}
LedgerProposal::LedgerProposal (uint256 const& prevLgr, uint256 const& position,
std::uint32_t closeTime) :
mPreviousLedger (prevLgr), mCurrentHash (position), mCloseTime (closeTime), mProposeSeq (0)
LedgerProposal::LedgerProposal (
RippleAddress const& publicKey,
uint256 const& prevLgr,
uint256 const& position,
std::uint32_t closeTime)
: mPreviousLedger (prevLgr)
, mCurrentHash (position)
, mCloseTime (closeTime)
, mProposeSeq (seqJoin)
, mPublicKey (publicKey)
{
if (mPublicKey.isValid ())
mPeerID = mPublicKey.getNodeID ();
mTime = std::chrono::steady_clock::now ();
}
@@ -70,42 +74,17 @@ uint256 LedgerProposal::getSigningHash () const
return s.getSHA512Half ();
}
/*
The "id" is a unique value computed on all fields that contribute to
the signature, and including the signature. There is one caveat, the
"last closed ledger" field may be omitted. However, the signer still
computes the signature as if this field was present. Recipients of
the proposal need to inject the last closed ledger in order to
validate the signature. If the last closed ledger is left out, then
it is considered as all zeroes for the purposes of signing.
*/
// Compute a unique identifier for this signed proposal
uint256 LedgerProposal::computeSuppressionID (
uint256 const& proposeHash,
uint256 const& previousLedger,
std::uint32_t proposeSeq,
std::uint32_t closeTime,
Blob const& pubKey,
Blob const& signature)
bool LedgerProposal::checkSign (std::string const& signature) const
{
Serializer s (512);
s.add256 (proposeHash);
s.add256 (previousLedger);
s.add32 (proposeSeq);
s.add32 (closeTime);
s.addVL (pubKey);
s.addVL (signature);
return s.getSHA512Half ();
return mPublicKey.verifyNodePublic (
getSigningHash (),
signature,
ECDSA::not_strict);
}
bool LedgerProposal::checkSign (std::string const& signature, uint256 const& signingHash)
{
return mPublicKey.verifyNodePublic (signingHash, signature, ECDSA::not_strict);
}
bool LedgerProposal::changePosition (uint256 const& newPosition, std::uint32_t closeTime)
bool LedgerProposal::changePosition (
uint256 const& newPosition,
std::uint32_t closeTime)
{
if (mProposeSeq == seqLeave)
return false;
@@ -123,18 +102,12 @@ void LedgerProposal::bowOut ()
mProposeSeq = seqLeave;
}
Blob LedgerProposal::sign (void)
Blob LedgerProposal::sign (RippleAddress const& privateKey)
{
Blob ret;
mPrivateKey.signNodePrivate (getSigningHash (), ret);
// XXX If this can fail, find out sooner.
// if (!mPrivateKey.signNodePrivate(getSigningHash(), ret))
// throw std::runtime_error("unable to sign proposal");
mSuppression = computeSuppressionID (mCurrentHash, mPreviousLedger, mProposeSeq,
privateKey.signNodePrivate (getSigningHash (), ret);
mSuppression = proposalUniqueId (mCurrentHash, mPreviousLedger, mProposeSeq,
mCloseTime, mPublicKey.getNodePublic (), ret);
return ret;
}
@@ -157,4 +130,24 @@ Json::Value LedgerProposal::getJson () const
return ret;
}
uint256 proposalUniqueId (
uint256 const& proposeHash,
uint256 const& previousLedger,
std::uint32_t proposeSeq,
std::uint32_t closeTime,
Blob const& pubKey,
Blob const& signature)
{
Serializer s (512);
s.add256 (proposeHash);
s.add256 (previousLedger);
s.add32 (proposeSeq);
s.add32 (closeTime);
s.addVL (pubKey);
s.addVL (signature);
return s.getSHA512Half ();
}
} // ripple

View File

@@ -24,7 +24,7 @@
#include <ripple/basics/base_uint.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/RippleAddress.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <chrono>
#include <cstdint>
#include <string>
@@ -33,35 +33,38 @@ namespace ripple {
class LedgerProposal
: public CountedObject <LedgerProposal>
{
private:
// A peer initial joins the consensus process
static std::uint32_t const seqJoin = 0;
// A peer wants to bow out and leave the consensus process
static std::uint32_t const seqLeave = 0xffffffff;
public:
static char const* getCountedObjectName () { return "LedgerProposal"; }
static const std::uint32_t seqLeave = 0xffffffff; // leaving the consensus process
using pointer = std::shared_ptr<LedgerProposal>;
using ref = const pointer&;
// proposal from peer
LedgerProposal (uint256 const& prevLgr, std::uint32_t proposeSeq, uint256 const& propose,
std::uint32_t closeTime, const RippleAddress & naPeerPublic, uint256 const& suppress);
LedgerProposal (
uint256 const& prevLgr,
std::uint32_t proposeSeq,
uint256 const& propose,
std::uint32_t closeTime,
RippleAddress const& publicKey,
uint256 const& suppress);
// our first proposal
LedgerProposal (const RippleAddress & pubKey, const RippleAddress & privKey,
uint256 const& prevLedger, uint256 const& position, std::uint32_t closeTime);
// an unsigned "dummy" proposal for nodes not validating
LedgerProposal (uint256 const& prevLedger, uint256 const& position, std::uint32_t closeTime);
// Our own proposal: the publicKey, if set, indicates we are a validating
// node but does not indicate if we're validating in this consensus round.
LedgerProposal (
RippleAddress const& publicKey,
uint256 const& prevLedger,
uint256 const& position,
std::uint32_t closeTime);
uint256 getSigningHash () const;
bool checkSign (std::string const& signature, uint256 const& signingHash);
bool checkSign (std::string const& signature)
{
return checkSign (signature, getSigningHash ());
}
bool checkSign ()
{
return checkSign (mSignature, getSigningHash ());
}
bool checkSign (std::string const& signature) const;
NodeID const& getPeerID () const
{
@@ -87,42 +90,23 @@ public:
{
return mCloseTime;
}
RippleAddress const& peekPublic () const
{
return mPublicKey;
}
Blob getPubKey () const
{
return mPublicKey.getNodePublic ();
}
Blob sign ();
void setPrevLedger (uint256 const& prevLedger)
{
mPreviousLedger = prevLedger;
}
void setSignature (std::string const& signature)
{
mSignature = signature;
}
bool hasSignature ()
{
return !mSignature.empty ();
}
bool isPrevLedger (uint256 const& pl)
Blob sign (RippleAddress const& privateKey);
bool isPrevLedger (uint256 const& pl) const
{
return mPreviousLedger == pl;
}
bool isBowOut ()
bool isInitial () const
{
return mProposeSeq == seqJoin;
}
bool isBowOut () const
{
return mProposeSeq == seqLeave;
}
std::chrono::steady_clock::time_point getCreateTime ()
{
return mTime;
}
bool isStale (std::chrono::steady_clock::time_point cutoff)
bool isStale (std::chrono::steady_clock::time_point cutoff) const
{
return mTime <= cutoff;
}
@@ -131,7 +115,26 @@ public:
void bowOut ();
Json::Value getJson () const;
static uint256 computeSuppressionID (
private:
uint256 mPreviousLedger, mCurrentHash, mSuppression;
std::uint32_t mCloseTime, mProposeSeq;
NodeID mPeerID;
RippleAddress mPublicKey;
std::chrono::steady_clock::time_point mTime;
};
/** Calculate a unique identifier for a signed proposal.
The identifier is based on all the fields that contribute to the signature,
as well as the signature itself. The "last closed ledger" field may be
omitted, but the signer will compute the signature as if this
field was present. Recipients of the proposal will inject the last closed
ledger in order to validate the signature. If the last closed ledger is left
out, then it is considered as all zeroes for the purposes of signing.
*/
uint256 proposalUniqueId (
uint256 const& proposeHash,
uint256 const& previousLedger,
std::uint32_t proposeSeq,
@@ -139,18 +142,6 @@ public:
Blob const& pubKey,
Blob const& signature);
private:
uint256 mPreviousLedger, mCurrentHash, mSuppression;
std::uint32_t mCloseTime, mProposeSeq;
NodeID mPeerID;
RippleAddress mPublicKey;
RippleAddress mPrivateKey; // If ours
std::string mSignature; // set only if needed
std::chrono::steady_clock::time_point mTime;
};
} // ripple
#endif

View File

@@ -88,6 +88,15 @@ int getNextLedgerTimeResolution (
bool previousAgree,
std::uint32_t ledgerSeq);
/** Calculates the close time for a ledger, given a close time resolution.
@param closeTime The time to be rouned.
@param closeResolution The resolution
*/
std::uint32_t roundCloseTime (
std::uint32_t closeTime,
std::uint32_t closeResolution);
//------------------------------------------------------------------------------
// These are protocol parameters used to control the behavior of the system and

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/ledger/DisputedTx.h>
#include <ripple/app/ledger/impl/DisputedTx.h>
#include <ripple/app/ledger/LedgerTiming.h>
#include <ripple/basics/Log.h>
#include <ripple/json/to_string.h>

View File

@@ -18,10 +18,10 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerCleaner.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/impl/LedgerCleaner.h>
#include <ripple/app/main/Application.h>
#include <ripple/core/LoadFeeTrack.h>
#include <ripple/protocol/JsonFields.h>

View File

@@ -18,12 +18,12 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/ledger/DisputedTx.h>
#include <ripple/app/ledger/LedgerConsensus.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerTiming.h>
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/ledger/impl/DisputedTx.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/AmendmentTable.h>
#include <ripple/app/misc/CanonicalTXSet.h>
@@ -31,7 +31,6 @@
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/Validations.h>
#include <ripple/app/tx/TransactionAcquire.h>
#include <ripple/app/tx/InboundTransactions.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/basics/Log.h>
#include <ripple/core/Config.h>
@@ -66,6 +65,22 @@ class LedgerConsensusImp
, 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.
@@ -78,21 +93,30 @@ public:
LedgerConsensusImp& operator=(LedgerConsensusImp const&) = delete;
/**
The result of applying a transaction to a ledger.
@param localtx A set of local transactions to apply.
@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 Last Closed Ledger (LCL)
was.
@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 (LocalTxs& localtx,
LedgerHash const & prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote)
: m_localTX (localtx)
LedgerConsensusImp (
int previousProposers,
int previousConvergeTime,
InboundTransactions& inboundTransactions,
LocalTxs& localtx,
LedgerHash const & prevLCLHash,
Ledger::ref previousLedger,
std::uint32_t closeTime,
FeeVote& feeVote)
: inboundTransactions_ (inboundTransactions)
, m_localTX (localtx)
, m_feeVote (feeVote)
, mState (lcsPRE_CLOSE)
, state_ (State::open)
, mCloseTime (closeTime)
, mPrevLedgerHash (prevLCLHash)
, mPreviousLedger (previousLedger)
@@ -102,23 +126,23 @@ public:
, mCurrentMSeconds (0)
, mClosePercent (0)
, mHaveCloseTimeConsensus (false)
, mConsensusStartTime
(std::chrono::steady_clock::now ())
, mConsensusStartTime (std::chrono::steady_clock::now ())
, mPreviousProposers (previousProposers)
, mPreviousMSeconds (previousConvergeTime)
{
WriteLog (lsDEBUG, LedgerConsensus) << "Creating consensus object";
WriteLog (lsTRACE, LedgerConsensus)
<< "LCL:" << previousLedger->getHash () << ", ct=" << closeTime;
mPreviousProposers = getApp().getOPs ().getPreviousProposers ();
mPreviousMSeconds = getApp().getOPs ().getPreviousConvergeTime ();
assert (mPreviousMSeconds);
getApp().getInboundTransactions().newRound (mPreviousLedger->getLedgerSeq());
inboundTransactions_.newRound (mPreviousLedger->getLedgerSeq());
// Adapt close time resolution to recent network conditions
mCloseResolution = getNextLedgerTimeResolution (
mPreviousLedger->getCloseResolution (),
mPreviousLedger->getCloseAgree (),
previousLedger->getLedgerSeq () + 1);
mPreviousLedger->getLedgerSeq () + 1);
if (mValPublic.isSet () && mValPrivate.isSet ()
&& !getApp().getOPs ().isNeedNetworkLedger ())
@@ -163,16 +187,6 @@ public:
getApp().getOPs ().setProposing (mProposing, mValidating);
}
/**
This function is called, but its return value is always ignored.
@return 1.
*/
int startup ()
{
return 1;
}
/**
Get the Json state of the consensus process.
Called by the consensus_info RPC.
@@ -196,21 +210,21 @@ public:
else
ret["synched"] = false;
switch (mState)
switch (state_)
{
case lcsPRE_CLOSE:
case State::open:
ret[jss::state] = "open";
break;
case lcsESTABLISH:
case State::establish:
ret[jss::state] = "consensus";
break;
case lcsFINISHED:
case State::finished:
ret[jss::state] = "finished";
break;
case lcsACCEPTED:
case State::accepted:
ret[jss::state] = "accepted";
break;
}
@@ -356,7 +370,7 @@ public:
if (!acquired)
{
// Put the map where others can get it
getApp().getInboundTransactions().giveSet (hash, map, false);
inboundTransactions_.giveSet (hash, map, false);
}
// Inform directly-connected peers that we have this transaction set
@@ -445,22 +459,22 @@ public:
// LCL change
const char* status;
switch (mState)
switch (state_)
{
case lcsPRE_CLOSE:
status = "PreClose";
case State::open:
status = "open";
break;
case lcsESTABLISH:
status = "Establish";
case State::establish:
status = "establish";
break;
case lcsFINISHED:
status = "Finished";
case State::finished:
status = "finished";
break;
case lcsACCEPTED:
status = "Accepted";
case State::accepted:
status = "accepted";
break;
default:
@@ -531,13 +545,14 @@ public:
return;
// we need to switch the ledger we're working from
Ledger::pointer newLCL = getApp().getLedgerMaster ().getLedgerByHash (mPrevLedgerHash);
auto newLCL = getApp().getLedgerMaster ().getLedgerByHash (mPrevLedgerHash);
if (!newLCL)
{
if (mAcquiringLedger != lclHash)
{
// need to start acquiring the correct consensus LCL
WriteLog (lsWARNING, LedgerConsensus) << "Need consensus ledger " << mPrevLedgerHash;
WriteLog (lsWARNING, LedgerConsensus) <<
"Need consensus ledger " << mPrevLedgerHash;
// Tell the ledger acquire system that we need the consensus ledger
mAcquiringLedger = mPrevLedgerHash;
@@ -556,7 +571,8 @@ public:
mPreviousLedger = newLCL;
mPrevLedgerHash = lclHash;
WriteLog (lsINFO, LedgerConsensus) << "Have the consensus ledger " << mPrevLedgerHash;
WriteLog (lsINFO, LedgerConsensus) <<
"Have the consensus ledger " << mPrevLedgerHash;
mHaveCorrectLCL = true;
mCloseResolution = getNextLedgerTimeResolution (
@@ -587,34 +603,34 @@ public:
void doTimer ()
{
if ((mState != lcsFINISHED) && (mState != lcsACCEPTED))
if ((state_ != State::finished) && (state_ != State::accepted))
checkLCL ();
mCurrentMSeconds = std::chrono::duration_cast <std::chrono::milliseconds>
(std::chrono::steady_clock::now() - mConsensusStartTime).count ();
mClosePercent = mCurrentMSeconds * 100 / mPreviousMSeconds;
switch (mState)
switch (state_)
{
case lcsPRE_CLOSE:
case State::open:
statePreClose ();
return;
case lcsESTABLISH:
case State::establish:
stateEstablish ();
if (mState != lcsFINISHED) return;
if (state_ != State::finished) return;
// Fall through
case lcsFINISHED:
case State::finished:
stateFinished ();
if (mState != lcsACCEPTED) return;
if (state_ != State::accepted) return;
// Fall through
case lcsACCEPTED:
case State::accepted:
stateAccepted ();
return;
}
@@ -696,7 +712,7 @@ public:
WriteLog (lsINFO, LedgerConsensus) <<
"Converge cutoff (" << mPeerPositions.size () << " participants)";
mState = lcsFINISHED;
state_ = State::finished;
beginAccept (false);
}
@@ -781,7 +797,7 @@ public:
if (it != mAcquired.end() && it->second)
return it->second;
auto set = getApp().getInboundTransactions().getSet (hash, true);
auto set = inboundTransactions_.getSet (hash, true);
if (set)
mAcquired[hash] = set;
@@ -798,7 +814,7 @@ public:
*/
bool peerPosition (LedgerProposal::ref newPosition)
{
auto peerID = newPosition->getPeerID ();
auto const peerID = newPosition->getPeerID ();
if (mDeadNodes.find (peerID) != mDeadNodes.end ())
{
@@ -820,17 +836,8 @@ public:
}
}
if (newPosition->getProposeSeq () == 0)
if (newPosition->isBowOut ())
{
// new initial close time estimate
WriteLog (lsTRACE, LedgerConsensus)
<< "Peer reports close time as "
<< newPosition->getCloseTime ();
++mCloseTimes[newPosition->getCloseTime ()];
}
else if (newPosition->getProposeSeq () == LedgerProposal::seqLeave)
{
// peer bows out
WriteLog (lsINFO, LedgerConsensus)
<< "Peer bows out: " << to_string (peerID);
for (auto& it : mDisputes)
@@ -840,6 +847,14 @@ public:
return true;
}
if (newPosition->isInitial ())
{
// Record the close time estimate
WriteLog (lsTRACE, LedgerConsensus)
<< "Peer reports close time as "
<< newPosition->getCloseTime ();
++mCloseTimes[newPosition->getCloseTime ()];
}
WriteLog (lsTRACE, LedgerConsensus) << "Processing peer proposal "
<< newPosition->getProposeSeq () << "/"
@@ -863,8 +878,6 @@ public:
return true;
}
/** Simulate a consensus round without any network traffic
*/
void simulate ()
{
WriteLog (lsINFO, LedgerConsensus) << "Simulating consensus";
@@ -874,6 +887,7 @@ public:
endConsensus ();
WriteLog (lsINFO, LedgerConsensus) << "Simulation complete";
}
private:
/** We have a new last closed ledger, process it. Final accept logic
@@ -881,9 +895,8 @@ private:
*/
void accept (std::shared_ptr<SHAMap> set)
{
{
std::lock_guard<Application::MutexType> lock(getApp().getMasterMutex());
auto lock = beast::make_lock(getApp().getMasterMutex());
// put our set where others can get it later
if (set->getHash ().isNonZero ())
@@ -895,7 +908,8 @@ private:
getApp().getOPs ().peekStoredProposals ().clear ();
}
std::uint32_t closeTime = roundCloseTime (mOurPosition->getCloseTime ());
std::uint32_t closeTime = roundCloseTime (
mOurPosition->getCloseTime (), mCloseResolution);
bool closeTimeCorrect = true;
if (closeTime == 0)
@@ -921,9 +935,7 @@ private:
CanonicalTXSet retriableTransactions (set->getHash ());
// Build the new last closed ledger
Ledger::pointer newLCL
= std::make_shared<Ledger> (false
, *mPreviousLedger);
auto newLCL = std::make_shared<Ledger> (false, *mPreviousLedger);
// Set up to write SHAMap changes to our database,
// perform updates, extract changes
@@ -981,7 +993,7 @@ private:
getApp().getAmendmentTable ().doValidation (newLCL, *v);
}
v->sign (signingHash, mValPrivate);
signingHash = v->sign (mValPrivate);
v->setTrusted ();
// suppress it if we receive it - FIXME: wrong suppression
getApp().getHashRouter ().addSuppression (signingHash);
@@ -1003,8 +1015,7 @@ private:
getApp().getLedgerMaster().consensusBuilt (newLCL);
// Build new open ledger
Ledger::pointer newOL = std::make_shared<Ledger>
(true, *newLCL);
auto newOL = std::make_shared<Ledger> (true, *newLCL);
// Apply disputed transactions that didn't get in
TransactionEngine engine (newOL);
@@ -1065,15 +1076,14 @@ private:
}
mNewLedgerHash = newLCL->getHash ();
mState = lcsACCEPTED;
state_ = State::accepted;
if (mValidating)
{
// see how close our close time is to other node's
// close time reports, and update our clock.
WriteLog (lsINFO, LedgerConsensus)
<< "We closed at "
<< beast::lexicalCastThrow <std::string> (mCloseTime);
<< "We closed at " << mCloseTime;
std::uint64_t closeTotal = mCloseTime;
int closeCount = 1;
@@ -1253,10 +1263,12 @@ private:
prop.set_proposeseq (mOurPosition->getProposeSeq ());
prop.set_closetime (mOurPosition->getCloseTime ());
Blob pubKey = mOurPosition->getPubKey ();
Blob sig = mOurPosition->sign ();
Blob const pubKey = mValPublic.getNodePublic ();
prop.set_nodepubkey (&pubKey[0], pubKey.size ());
Blob const sig = mOurPosition->sign (mValPrivate);
prop.set_signature (&sig[0], sig.size ());
getApp().overlay().send(prop);
}
@@ -1277,17 +1289,6 @@ private:
msg, protocol::mtHAVE_SET)));
}
/**
Round the close time to the close time resolution.
@param closeTime The time to be rouned.
@return The rounded close time.
*/
std::uint32_t roundCloseTime (std::uint32_t closeTime)
{
return Ledger::roundCloseTime (closeTime, mCloseResolution);
}
/** Send a node status change message to our directly connected peers
@param event The event which caused the status change. This is
@@ -1360,19 +1361,8 @@ private:
WriteLog (lsINFO, LedgerConsensus) << "initial position " << txSet;
mapCompleteInternal (txSet, initialSet, false);
if (mValidating)
{
mOurPosition = std::make_shared<LedgerProposal>
(mValPublic, mValPrivate
, initialLedger.getParentHash ()
, txSet, mCloseTime);
}
else
{
mOurPosition
= std::make_shared<LedgerProposal>
(initialLedger.getParentHash (), txSet, mCloseTime);
}
(mValPublic, initialLedger.getParentHash (), txSet, mCloseTime);
for (auto& it : mDisputes)
{
@@ -1402,17 +1392,22 @@ private:
propose ();
}
/**
For a given number of participants and required percent
for consensus, how many participants must agree?
/** How many of the participants must agree to reach a given threshold?
@param size number of validators
@param percent desired percent for consensus
@return number of participates which must agree
Note that the number may not precisely yield the requested percentage.
For example, with with size = 5 and percent = 70, we return 3, but
3 out of 5 works out to 60%. There are no security implications to
this.
@param participants the number of participants (i.e. validators)
@param the percent that we want to reach
@return the number of participants which must agree
*/
static int computePercent (int size, int percent)
static int participantsNeeded (int participants, int percent)
{
int result = ((size * percent) + (percent / 2)) / 100;
int result = ((participants * percent) + (percent / 2)) / 100;
return (result == 0) ? 1 : result;
}
@@ -1452,7 +1447,7 @@ private:
else
{
// proposal is still fresh
++closeTimes[roundCloseTime (it->second->getCloseTime ())];
++closeTimes[roundCloseTime (it->second->getCloseTime (), mCloseResolution)];
++it;
}
}
@@ -1504,22 +1499,24 @@ private:
{
// no other times
mHaveCloseTimeConsensus = true;
closeTime = roundCloseTime (mOurPosition->getCloseTime ());
closeTime = roundCloseTime (mOurPosition->getCloseTime (), mCloseResolution);
}
else
{
int participants = mPeerPositions.size ();
if (mProposing)
{
++closeTimes[roundCloseTime (mOurPosition->getCloseTime ())];
++closeTimes[roundCloseTime (mOurPosition->getCloseTime (), mCloseResolution)];
++participants;
}
// Threshold for non-zero vote
int threshVote = computePercent (participants, neededWeight);
int threshVote = participantsNeeded (participants,
neededWeight);
// Threshold to declare consensus
int threshConsensus = computePercent (participants, AV_CT_CONSENSUS_PCT);
int const threshConsensus = participantsNeeded (
participants, AV_CT_CONSENSUS_PCT);
WriteLog (lsINFO, LedgerConsensus) << "Proposers:"
<< mPeerPositions.size () << " nw:" << neededWeight
@@ -1559,7 +1556,7 @@ private:
}
if (!changes &&
((closeTime != roundCloseTime (mOurPosition->getCloseTime ()))
((closeTime != roundCloseTime (mOurPosition->getCloseTime (), mCloseResolution))
|| mOurPosition->isStale (ourCutoff)))
{
// close time changed or our position is stale
@@ -1596,20 +1593,7 @@ private:
bool relay = false;
for (auto const& proposal : it.second)
{
if (proposal->hasSignature ())
{
// we have the signature but don't know the
// ledger so couldn't verify
proposal->setPrevLedger (mPrevLedgerHash);
if (proposal->checkSign ())
{
WriteLog (lsINFO, LedgerConsensus)
<< "Applying stored proposal";
relay = peerPosition (proposal);
}
}
else if (proposal->isPrevLedger (mPrevLedgerHash))
if (proposal->isPrevLedger (mPrevLedgerHash))
relay = peerPosition (proposal);
if (relay)
@@ -1628,7 +1612,7 @@ private:
void closeLedger ()
{
checkOurValidation ();
mState = lcsESTABLISH;
state_ = State::establish;
mConsensusStartTime
= std::chrono::steady_clock::now ();
mCloseTime = getApp().getOPs ().getCloseTimeNC ();
@@ -1644,7 +1628,8 @@ private:
*/
void checkOurValidation ()
{
// This only covers some cases - Fix for the case where we can't ever acquire the consensus ledger
// This only covers some cases - Fix for the case where we can't ever
// acquire the consensus ledger
if (!mHaveCorrectLCL || !mValPublic.isSet ()
|| !mValPrivate.isSet ()
|| getApp().getOPs ().isNeedNetworkLedger ())
@@ -1673,7 +1658,7 @@ private:
, getApp().getOPs ().getValidationTimeNC (), mValPublic, false);
addLoad(v);
v->setTrusted ();
v->sign (signingHash, mValPrivate);
signingHash = v->sign (mValPrivate);
// FIXME: wrong supression
getApp().getHashRouter ().addSuppression (signingHash);
getApp().getValidations ().addValidation (v, "localMissing");
@@ -1716,8 +1701,7 @@ private:
getApp().getOPs ().endConsensus (mHaveCorrectLCL);
}
/** Add our load fee to our validation
*/
/** Add our load fee to our validation */
void addLoad(STValidation::ref val)
{
std::uint32_t fee = std::max(
@@ -1727,22 +1711,13 @@ private:
if (fee > ref)
val->setFieldU32(sfLoadFee, fee);
}
private:
InboundTransactions& inboundTransactions_;
LocalTxs& m_localTX;
FeeVote& m_feeVote;
// VFALCO TODO Rename these to look pretty
enum LCState
{
lcsPRE_CLOSE, // We haven't closed our ledger yet,
// but others might have
lcsESTABLISH, // Establishing consensus
lcsFINISHED, // We have closed on a transaction set
lcsACCEPTED, // We have accepted/validated
// a new last closed ledger
};
LCState mState;
State state_;
std::uint32_t mCloseTime; // The wall time this ledger closed
uint256 mPrevLedgerHash, mNewLedgerHash, mAcquiringLedger;
Ledger::pointer mPreviousLedger;
@@ -1750,11 +1725,20 @@ private:
RippleAddress mValPublic, mValPrivate;
bool mProposing, mValidating, mHaveCorrectLCL, mConsensusFail;
int mCurrentMSeconds, mClosePercent, mCloseResolution;
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
@@ -1771,7 +1755,7 @@ private:
std::map<std::uint32_t, int> mCloseTimes;
// nodes that have bowed out of this consensus process
NodeIDSet mDeadNodes;
hash_set<NodeID> mDeadNodes;
};
//------------------------------------------------------------------------------
@@ -1781,12 +1765,14 @@ LedgerConsensus::~LedgerConsensus ()
}
std::shared_ptr <LedgerConsensus>
make_LedgerConsensus (LocalTxs& localtx,
make_LedgerConsensus (int previousProposers, int previousConvergeTime,
InboundTransactions& inboundTransactions, LocalTxs& localtx,
LedgerHash const &prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote)
{
return std::make_shared <LedgerConsensusImp> (localtx,
prevLCLHash, previousLedger, closeTime, feeVote);
return std::make_shared <LedgerConsensusImp> (previousProposers,
previousConvergeTime, inboundTransactions, localtx, prevLCLHash,
previousLedger, closeTime, feeVote);
}
/** Apply a transaction to a ledger
@@ -1858,7 +1844,8 @@ int applyTransaction (TransactionEngine& engine
@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).
messages (typically new last closed
ledger).
@param retriableTransactions collect failed transactions in this set
@param openLgr true if applyLedger is open, else false.
*/

View File

@@ -20,11 +20,11 @@
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerCleaner.h>
#include <ripple/app/ledger/LedgerHistory.h>
#include <ripple/app/ledger/LedgerHolder.h>
#include <ripple/app/ledger/OrderBookDB.h>
#include <ripple/app/ledger/PendingSaves.h>
#include <ripple/app/ledger/impl/LedgerCleaner.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/IHashRouter.h>
#include <ripple/app/misc/NetworkOPs.h>

View File

@@ -179,4 +179,14 @@ int getNextLedgerTimeResolution (
return previousResolution;
}
std::uint32_t roundCloseTime (
std::uint32_t closeTime,
std::uint32_t closeResolution)
{
if (closeTime == 0)
return 0;
closeTime += (closeResolution / 2);
return closeTime - (closeTime % closeResolution);
}
} // ripple

View File

@@ -101,8 +101,8 @@ public:
, m_clusterTimer (this)
, m_ledgerMaster (ledgerMaster)
, mCloseTimeOffset (0)
, mLastCloseProposers (0)
, mLastCloseConvergeTime (1000 * LEDGER_IDLE_INTERVAL)
, lastCloseProposers_ (0)
, lastCloseConvergeTook_ (1000 * LEDGER_IDLE_INTERVAL)
, mLastCloseTime (0)
, mLastValidationTime (0)
, mFetchPack ("FetchPack", 65536, 45, clock,
@@ -278,7 +278,7 @@ public:
void processTrustedProposal (
LedgerProposal::pointer proposal,
std::shared_ptr<protocol::TMProposeSet> set,
RippleAddress nodePublic, uint256 checkLedger, bool sigGood) override;
RippleAddress const &nodePublic) override;
bool recvValidation (
STValidation::ref val, std::string const& source) override;
@@ -314,7 +314,7 @@ private:
Ledger::pointer newLedger, bool duringConsensus);
bool checkLastClosedLedger (
const Overlay::PeerSequence&, uint256& networkClosed);
int beginConsensus (
bool beginConsensus (
uint256 const& networkClosed, Ledger::pointer closingLedger);
void tryStartConsensus ();
@@ -367,14 +367,6 @@ public:
}
void setAmendmentBlocked () override;
void consensusViewChange () override;
int getPreviousProposers () override
{
return mLastCloseProposers;
}
int getPreviousConvergeTime () override
{
return mLastCloseConvergeTime;
}
std::uint32_t getLastCloseTime () override
{
return mLastCloseTime;
@@ -558,8 +550,6 @@ private:
bool mValidating;
bool m_amendmentBlocked;
boost::posix_time::ptime mConnectTime;
beast::DeadlineTimer m_heartbeatTimer;
beast::DeadlineTimer m_clusterTimer;
@@ -571,10 +561,14 @@ private:
int mCloseTimeOffset;
// last ledger close
int mLastCloseProposers;
int mLastCloseConvergeTime;
uint256 mLastCloseHash;
// 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;
@@ -1316,10 +1310,9 @@ bool NetworkOPsImp::checkLastClosedLedger (
auto current = getApp().getValidations ().getCurrentValidations (
closedLedger, prevClosedLedger);
using u256_cvc_pair = std::map<uint256, ValidationCounter>::value_type;
for (auto& it: current)
{
ValidationCount& vc = ledgers[it.first];
auto& vc = ledgers[it.first];
vc.trustedValidations += it.second.first;
if (it.second.second > vc.highValidation)
@@ -1327,7 +1320,7 @@ bool NetworkOPsImp::checkLastClosedLedger (
}
}
ValidationCount& ourVC = ledgers[closedLedger];
auto& ourVC = ledgers[closedLedger];
if (mMode >= omTRACKING)
{
@@ -1347,7 +1340,7 @@ bool NetworkOPsImp::checkLastClosedLedger (
{
try
{
ValidationCount& vc = ledgers[peerLedger];
auto& vc = ledgers[peerLedger];
if (vc.nodesUsing == 0 ||
peer->getNodePublic ().getNodeID () > vc.highNodeUsing)
@@ -1364,7 +1357,7 @@ bool NetworkOPsImp::checkLastClosedLedger (
}
}
ValidationCount bestVC = ledgers[closedLedger];
auto bestVC = ledgers[closedLedger];
// 3) Is there a network ledger we'd like to switch to? If so, do we have
// it?
@@ -1458,16 +1451,15 @@ void NetworkOPsImp::switchLastClosedLedger (
std::make_shared<Message> (s, protocol::mtSTATUS_CHANGE)));
}
int NetworkOPsImp::beginConsensus (
bool NetworkOPsImp::beginConsensus (
uint256 const& networkClosed, Ledger::pointer closingLedger)
{
m_journal.info
<< "Consensus time for ledger " << closingLedger->getLedgerSeq ();
m_journal.info
<< " LCL is " << closingLedger->getParentHash ();
if (m_journal.info) m_journal.info <<
"Consensus time for #" << closingLedger->getLedgerSeq () <<
" with LCL " << closingLedger->getParentHash ();
auto prevLedger
= m_ledgerMaster.getLedgerByHash (closingLedger->getParentHash ());
auto prevLedger = m_ledgerMaster.getLedgerByHash (
closingLedger->getParentHash ());
if (!prevLedger)
{
@@ -1478,7 +1470,7 @@ int NetworkOPsImp::beginConsensus (
setMode (omTRACKING);
}
return 3;
return false;
}
assert (prevLedger->getHash () == closingLedger->getParentHash ());
@@ -1489,12 +1481,18 @@ int NetworkOPsImp::beginConsensus (
assert (!mConsensus);
prevLedger->setImmutable ();
mConsensus = make_LedgerConsensus (*m_localTX, networkClosed,
prevLedger, m_ledgerMaster.getCurrentLedger ()->getCloseTimeNC (),
mConsensus = make_LedgerConsensus (
lastCloseProposers_,
lastCloseConvergeTook_,
getApp().getInboundTransactions(),
*m_localTX,
networkClosed,
prevLedger,
m_ledgerMaster.getCurrentLedger ()->getCloseTimeNC (),
*m_feeVote);
m_journal.debug << "Initiating consensus engine";
return mConsensus->startup ();
return true;
}
bool NetworkOPsImp::haveConsensusObject ()
@@ -1517,7 +1515,7 @@ bool NetworkOPsImp::haveConsensusObject ()
{
m_journal.info << "Beginning consensus due to peer action";
if ( ((mMode == omTRACKING) || (mMode == omSYNCING)) &&
(getPreviousProposers() >= m_ledgerMaster.getMinValidations()) )
(lastCloseProposers_ >= m_ledgerMaster.getMinValidations()) )
setMode (omFULL);
beginConsensus (networkClosed, m_ledgerMaster.getCurrentLedger ());
}
@@ -1536,8 +1534,7 @@ uint256 NetworkOPsImp::getConsensusLCL ()
void NetworkOPsImp::processTrustedProposal (
LedgerProposal::pointer proposal,
std::shared_ptr<protocol::TMProposeSet> set, RippleAddress nodePublic,
uint256 checkLedger, bool sigGood)
std::shared_ptr<protocol::TMProposeSet> set, const RippleAddress& nodePublic)
{
{
auto lock = beast::make_lock(getApp().getMasterMutex());
@@ -1555,21 +1552,7 @@ void NetworkOPsImp::processTrustedProposal (
{
storeProposal (proposal, nodePublic);
uint256 consensusLCL = mConsensus->getLCL ();
if (!set->has_previousledger () && (checkLedger != consensusLCL))
{
m_journal.warning
<< "Have to re-check proposal signature due to "
<< "consensus view change";
assert (proposal->hasSignature ());
proposal->setPrevLedger (consensusLCL);
if (proposal->checkSign ())
sigGood = true;
}
if (sigGood && (consensusLCL == proposal->getPrevLedger ()))
if (mConsensus->getLCL () == proposal->getPrevLedger ())
{
relay = mConsensus->peerPosition (proposal);
m_journal.trace
@@ -1685,7 +1668,6 @@ void NetworkOPsImp::pubServer ()
void NetworkOPsImp::setMode (OperatingMode om)
{
if (om == omCONNECTED)
{
if (getApp().getLedgerMaster ().getValidatedLedgerAge () < 60)
@@ -1703,14 +1685,9 @@ void NetworkOPsImp::setMode (OperatingMode om)
if (mMode == om)
return;
if ((om >= omCONNECTED) && (mMode == omDISCONNECTED))
mConnectTime = boost::posix_time::second_clock::universal_time ();
mMode = om;
m_journal.stream((om < mMode)
? beast::Journal::kWarning : beast::Journal::kInfo)
<< "STATE->" << strOperatingMode ();
m_journal.info << "STATE->" << strOperatingMode ();
pubServer ();
}
@@ -2060,17 +2037,17 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
info[jss::peers] = Json::UInt (getApp ().overlay ().size ());
Json::Value lastClose = Json::objectValue;
lastClose[jss::proposers] = getApp().getOPs ().getPreviousProposers ();
lastClose[jss::proposers] = lastCloseProposers_;
if (human)
{
lastClose[jss::converge_time_s] = static_cast<double> (
getApp().getOPs ().getPreviousConvergeTime ()) / 1000.0;
lastCloseConvergeTook_) / 1000.0;
}
else
{
lastClose[jss::converge_time] =
Json::Int (getApp().getOPs ().getPreviousConvergeTime ());
Json::Int (lastCloseConvergeTook_);
}
info[jss::last_close] = lastClose;
@@ -2592,14 +2569,22 @@ void NetworkOPsImp::newLCL (
int proposers, int convergeTime, uint256 const& ledgerHash)
{
assert (convergeTime);
mLastCloseProposers = proposers;
mLastCloseConvergeTime = convergeTime;
mLastCloseHash = ledgerHash;
lastCloseProposers_ = proposers;
lastCloseConvergeTook_ = convergeTime;
lastCloseHash_ = ledgerHash;
}
std::uint32_t NetworkOPsImp::acceptLedger ()
{
// accept the current transaction tree, return the new ledger's sequence
// This code-path is exclusively used when the server is in standalone
// mode via `ledger_accept`
assert (m_standalone);
if (!m_standalone)
throw std::runtime_error ("Operation only possible in STANDALONE mode.");
// FIXME Could we improve on this and remove the need for a specialized
// API in LedgerConsensus?
beginConsensus (
m_ledgerMaster.getClosedLedger ()->getHash (),
m_ledgerMaster.getCurrentLedger ());
@@ -2612,7 +2597,7 @@ void NetworkOPsImp::storeProposal (
{
auto& props = mStoredProposals[peerPublic.getNodeID ()];
if (props.size () >= (unsigned) (mLastCloseProposers + 10))
if (props.size () >= (unsigned) (lastCloseProposers_ + 10))
props.pop_front ();
props.push_back (proposal);

View File

@@ -212,8 +212,8 @@ public:
// ledger proposal/close functions
virtual void processTrustedProposal (LedgerProposal::pointer proposal,
std::shared_ptr<protocol::TMProposeSet> set, RippleAddress nodePublic,
uint256 checkLedger, bool sigGood) = 0;
std::shared_ptr<protocol::TMProposeSet> set,
RippleAddress const& nodePublic) = 0;
virtual bool recvValidation (STValidation::ref val,
std::string const& source) = 0;
@@ -255,8 +255,6 @@ public:
virtual bool isAmendmentBlocked () = 0;
virtual void setAmendmentBlocked () = 0;
virtual void consensusViewChange () = 0;
virtual int getPreviousProposers () = 0;
virtual int getPreviousConvergeTime () = 0;
virtual std::uint32_t getLastCloseTime () = 0;
virtual void setLastCloseTime (std::uint32_t t) = 0;
@@ -264,6 +262,13 @@ public:
virtual Json::Value getServerInfo (bool human, bool admin) = 0;
virtual void clearLedgerFetch () = 0;
virtual Json::Value getLedgerFetchInfo () = 0;
/** Accepts the current transaction tree, return the new ledger's sequence
This API is only used via RPC with the server in STANDALONE mode and
performs a virtual consensus round, with all the transactions we are
proposing being accepted.
*/
virtual std::uint32_t acceptLedger () = 0;
using Proposals = hash_map <NodeID, std::deque<LedgerProposal::pointer>>;

View File

@@ -1130,7 +1130,7 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
return;
}
if (set.has_previousledger () && (set.previousledger ().size () != 32))
if (set.previousledger ().size () != 32)
{
p_journal_.warning << "Proposal: malformed";
fee_ = Resource::feeInvalidRequest;
@@ -1139,17 +1139,14 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
uint256 proposeHash, prevLedger;
memcpy (proposeHash.begin (), set.currenttxhash ().data (), 32);
if (set.has_previousledger ())
memcpy (prevLedger.begin (), set.previousledger ().data (), 32);
uint256 suppression = LedgerProposal::computeSuppressionID (
uint256 suppression = proposalUniqueId (
proposeHash, prevLedger, set.proposeseq(), set.closetime (),
Blob(set.nodepubkey ().begin (), set.nodepubkey ().end ()),
Blob(set.signature ().begin (), set.signature ().end ()));
if (! getApp().getHashRouter ().addSuppressionPeer (
suppression, id_))
if (! getApp().getHashRouter ().addSuppressionPeer (suppression, id_))
{
p_journal_.trace << "Proposal: duplicate";
return;
@@ -1166,24 +1163,26 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
bool isTrusted = getApp().getUNL ().nodeInUNL (signerPublic);
if (!isTrusted && (sanity_.load() == Sanity::insane))
if (!isTrusted)
{
if (sanity_.load() == Sanity::insane)
{
p_journal_.debug << "Proposal: Dropping UNTRUSTED (insane)";
return;
}
if (!isTrusted && getApp().getFeeTrack ().isLoadedLocal ())
if (getApp().getFeeTrack ().isLoadedLocal ())
{
p_journal_.debug << "Proposal: Dropping UNTRUSTED (load)";
return;
}
}
p_journal_.trace <<
"Proposal: " << (isTrusted ? "trusted" : "UNTRUSTED");
LedgerProposal::pointer proposal = std::make_shared<LedgerProposal> (
prevLedger.isNonZero () ? prevLedger : uint256(),
set.proposeseq (), proposeHash, set.closetime (),
auto proposal = std::make_shared<LedgerProposal> (
prevLedger, set.proposeseq (), proposeHash, set.closetime (),
signerPublic, suppression);
getApp().getJobQueue ().addJob (isTrusted ? jtPROPOSAL_t : jtPROPOSAL_ut,
@@ -1695,7 +1694,6 @@ PeerImp::checkPropose (Job& job,
std::shared_ptr <protocol::TMProposeSet> const& packet,
LedgerProposal::pointer proposal)
{
bool sigGood = false;
bool isTrusted = (job.getType () == jtPROPOSAL_t);
p_journal_.trace <<
@@ -1704,56 +1702,28 @@ PeerImp::checkPropose (Job& job,
assert (packet);
protocol::TMProposeSet& set = *packet;
uint256 consensusLCL;
if (! set.has_previousledger() || ! isTrusted)
{
std::lock_guard<Application::MutexType> lock(getApp().getMasterMutex());
consensusLCL = getApp().getOPs ().getConsensusLCL ();
}
uint256 prevLedger;
if (set.has_previousledger ())
{
// proposal includes a previous ledger
p_journal_.trace <<
"proposal with previous ledger";
memcpy (prevLedger.begin (), set.previousledger ().data (), 256 / 8);
proposal->setPrevLedger (prevLedger);
if (! cluster() && ! proposal->checkSign (set.signature ()))
{
p_journal_.warning <<
"Proposal with previous ledger fails sig check";
"Proposal fails sig check";
charge (Resource::feeInvalidSignature);
return;
}
else
sigGood = true;
}
else
{
proposal->setPrevLedger (consensusLCL);
if (consensusLCL.isNonZero () && proposal->checkSign (set.signature ()))
{
prevLedger = consensusLCL;
sigGood = true;
}
else
{
// Could be mismatched prev ledger
p_journal_.warning <<
"Ledger proposal fails signature check";
proposal->setSignature (set.signature ());
}
}
if (isTrusted)
{
getApp().getOPs ().processTrustedProposal (
proposal, packet, publicKey_, prevLedger, sigGood);
proposal, packet, publicKey_);
}
else if (sigGood && (prevLedger == consensusLCL))
else
{
uint256 consensusLCL;
{
std::lock_guard<Application::MutexType> lock (getApp().getMasterMutex());
consensusLCL = getApp().getOPs ().getConsensusLCL ();
}
if (consensusLCL == proposal->getPrevLedger())
{
// relay untrusted proposal
p_journal_.trace <<
@@ -1766,6 +1736,7 @@ PeerImp::checkPropose (Job& job,
"Not relaying UNTRUSTED proposal";
}
}
}
void
PeerImp::checkValidation (Job&, STValidation::pointer val,

View File

@@ -186,7 +186,7 @@ message TMProposeSet
required bytes nodePubKey = 3;
required uint32 closeTime = 4;
required bytes signature = 5; // signature of above fields
optional bytes previousledger = 6;
required bytes previousledger = 6;
optional bool checkedSignature = 7; // node vouches signature is correct
repeated bytes addedTransactions = 10; // not required if number is large
repeated bytes removedTransactions = 11; // not required if number is large

View File

@@ -87,8 +87,9 @@ public:
}
Blob getSigned () const;
Blob getSignature () const;
void sign (uint256 & signingHash, const RippleAddress & raPrivate);
void sign (const RippleAddress & raPrivate);
// Signs the validation and returns the signing hash
uint256 sign (const RippleAddress & raPrivate);
// The validation this replaced
uint256 const& getPreviousHash ()

View File

@@ -47,7 +47,6 @@ using Currency = base_uint<160, detail::CurrencyTag>;
using NodeID = base_uint<160, detail::NodeIDTag>;
using CurrencySet = hash_set<Currency>;
using NodeIDSet = hash_set<NodeID>;
/** A special account that's used as the "issuer" for XRP. */
Account const& xrpAccount();

View File

@@ -57,20 +57,16 @@ STValidation::STValidation (
setFlag (kFullFlag);
}
void STValidation::sign (RippleAddress const& raPriv)
{
uint256 signingHash;
sign (signingHash, raPriv);
}
void STValidation::sign (uint256& signingHash, RippleAddress const& raPriv)
uint256 STValidation::sign (RippleAddress const& raPriv)
{
setFlag (vfFullyCanonicalSig);
signingHash = getSigningHash ();
auto signingHash = getSigningHash ();
Blob signature;
raPriv.signNodePrivate (signingHash, signature);
setFieldVL (sfSignature, signature);
return signingHash;
}
uint256 STValidation::getSigningHash () const

View File

@@ -26,22 +26,22 @@
#include <ripple/app/ledger/ConsensusTransSetSF.cpp>
#include <ripple/app/ledger/DeferredCredits.cpp>
#include <ripple/app/ledger/DirectoryEntryIterator.cpp>
#include <ripple/app/ledger/DisputedTx.cpp>
#include <ripple/app/ledger/InboundLedger.cpp>
#include <ripple/app/ledger/InboundLedgers.cpp>
#include <ripple/app/ledger/Ledger.cpp>
#include <ripple/app/ledger/LedgerConsensus.cpp>
#include <ripple/app/ledger/LedgerCleaner.cpp>
#include <ripple/app/ledger/LedgerEntrySet.cpp>
#include <ripple/app/ledger/LedgerHistory.cpp>
#include <ripple/app/ledger/LedgerMaster.cpp>
#include <ripple/app/ledger/LedgerProposal.cpp>
#include <ripple/app/ledger/LedgerTiming.cpp>
#include <ripple/app/ledger/OrderBookDB.cpp>
#include <ripple/app/ledger/OrderBookIterator.cpp>
#include <ripple/app/ledger/TransactionStateSF.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/LedgerFees.cpp>
#include <ripple/app/ledger/impl/LedgerMaster.cpp>
#include <ripple/app/ledger/impl/LedgerTiming.cpp>
#include <ripple/app/ledger/tests/common_ledger.cpp>
#include <ripple/app/ledger/tests/DeferredCredits.test.cpp>