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

View File

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

View File

@@ -27,7 +27,6 @@
namespace ripple { namespace ripple {
// VFALCO TODO Rename to InboundLedger
// A ledger we are trying to acquire // A ledger we are trying to acquire
class InboundLedger class InboundLedger
: public PeerSet : 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 /** Save, or arrange to save, a fully-validated ledger
Returns false on error Returns false on error
*/ */

View File

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

View File

@@ -24,6 +24,7 @@
#include <ripple/app/ledger/LedgerProposal.h> #include <ripple/app/ledger/LedgerProposal.h>
#include <ripple/app/misc/CanonicalTXSet.h> #include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/app/misc/FeeVote.h> #include <ripple/app/misc/FeeVote.h>
#include <ripple/app/tx/InboundTransactions.h>
#include <ripple/app/tx/LocalTxs.h> #include <ripple/app/tx/LocalTxs.h>
#include <ripple/json/json_value.h> #include <ripple/json/json_value.h>
#include <ripple/overlay/Peer.h> #include <ripple/overlay/Peer.h>
@@ -42,8 +43,6 @@ class LedgerConsensus
public: public:
virtual ~LedgerConsensus() = 0; virtual ~LedgerConsensus() = 0;
virtual int startup () = 0;
virtual Json::Value getJson (bool full) = 0; virtual Json::Value getJson (bool full) = 0;
virtual uint256 getLCL () = 0; virtual uint256 getLCL () = 0;
@@ -55,12 +54,22 @@ public:
virtual bool peerPosition (LedgerProposal::ref) = 0; 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; virtual void simulate () = 0;
}; };
std::shared_ptr <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, LedgerHash const & prevLCLHash, Ledger::ref previousLedger,
std::uint32_t closeTime, FeeVote& feeVote); std::uint32_t closeTime, FeeVote& feeVote);

View File

@@ -26,34 +26,38 @@
namespace ripple { namespace ripple {
LedgerProposal::LedgerProposal (uint256 const& pLgr, std::uint32_t seq, LedgerProposal::LedgerProposal (
uint256 const& tx, std::uint32_t closeTime, uint256 const& pLgr,
RippleAddress const& naPeerPublic, uint256 const& suppression) : std::uint32_t seq,
mPreviousLedger (pLgr), mCurrentHash (tx), mSuppression (suppression), mCloseTime (closeTime), uint256 const& tx,
mProposeSeq (seq), mPublicKey (naPeerPublic) std::uint32_t closeTime,
{ RippleAddress const& publicKey,
// XXX Validate key. uint256 const& suppression)
// if (!mKey->SetPubKey(pubKey)) : mPreviousLedger (pLgr)
// throw std::runtime_error("Invalid public key in proposal"); , mCurrentHash (tx)
, mSuppression (suppression)
mPeerID = mPublicKey.getNodeID (); , mCloseTime (closeTime)
mTime = std::chrono::steady_clock::now (); , mProposeSeq (seq)
} , mPublicKey (publicKey)
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)
{ {
mPeerID = mPublicKey.getNodeID (); mPeerID = mPublicKey.getNodeID ();
mTime = std::chrono::steady_clock::now (); mTime = std::chrono::steady_clock::now ();
} }
LedgerProposal::LedgerProposal (uint256 const& prevLgr, uint256 const& position, LedgerProposal::LedgerProposal (
std::uint32_t closeTime) : RippleAddress const& publicKey,
mPreviousLedger (prevLgr), mCurrentHash (position), mCloseTime (closeTime), mProposeSeq (0) 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 (); mTime = std::chrono::steady_clock::now ();
} }
@@ -70,42 +74,17 @@ uint256 LedgerProposal::getSigningHash () const
return s.getSHA512Half (); return s.getSHA512Half ();
} }
/* bool LedgerProposal::checkSign (std::string const& signature) const
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)
{ {
return mPublicKey.verifyNodePublic (
Serializer s (512); getSigningHash (),
s.add256 (proposeHash); signature,
s.add256 (previousLedger); ECDSA::not_strict);
s.add32 (proposeSeq);
s.add32 (closeTime);
s.addVL (pubKey);
s.addVL (signature);
return s.getSHA512Half ();
} }
bool LedgerProposal::checkSign (std::string const& signature, uint256 const& signingHash) bool LedgerProposal::changePosition (
{ uint256 const& newPosition,
return mPublicKey.verifyNodePublic (signingHash, signature, ECDSA::not_strict); std::uint32_t closeTime)
}
bool LedgerProposal::changePosition (uint256 const& newPosition, std::uint32_t closeTime)
{ {
if (mProposeSeq == seqLeave) if (mProposeSeq == seqLeave)
return false; return false;
@@ -123,18 +102,12 @@ void LedgerProposal::bowOut ()
mProposeSeq = seqLeave; mProposeSeq = seqLeave;
} }
Blob LedgerProposal::sign (void) Blob LedgerProposal::sign (RippleAddress const& privateKey)
{ {
Blob ret; Blob ret;
privateKey.signNodePrivate (getSigningHash (), ret);
mPrivateKey.signNodePrivate (getSigningHash (), ret); mSuppression = proposalUniqueId (mCurrentHash, mPreviousLedger, mProposeSeq,
// 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,
mCloseTime, mPublicKey.getNodePublic (), ret); mCloseTime, mPublicKey.getNodePublic (), ret);
return ret; return ret;
} }
@@ -157,4 +130,24 @@ Json::Value LedgerProposal::getJson () const
return ret; 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 } // ripple

View File

@@ -24,7 +24,7 @@
#include <ripple/basics/base_uint.h> #include <ripple/basics/base_uint.h>
#include <ripple/json/json_value.h> #include <ripple/json/json_value.h>
#include <ripple/protocol/RippleAddress.h> #include <ripple/protocol/RippleAddress.h>
#include <boost/date_time/posix_time/posix_time.hpp> #include <chrono>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
@@ -33,35 +33,38 @@ namespace ripple {
class LedgerProposal class LedgerProposal
: public CountedObject <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: public:
static char const* getCountedObjectName () { return "LedgerProposal"; } static char const* getCountedObjectName () { return "LedgerProposal"; }
static const std::uint32_t seqLeave = 0xffffffff; // leaving the consensus process
using pointer = std::shared_ptr<LedgerProposal>; using pointer = std::shared_ptr<LedgerProposal>;
using ref = const pointer&; using ref = const pointer&;
// proposal from peer // proposal from peer
LedgerProposal (uint256 const& prevLgr, std::uint32_t proposeSeq, uint256 const& propose, LedgerProposal (
std::uint32_t closeTime, const RippleAddress & naPeerPublic, uint256 const& suppress); uint256 const& prevLgr,
std::uint32_t proposeSeq,
uint256 const& propose,
std::uint32_t closeTime,
RippleAddress const& publicKey,
uint256 const& suppress);
// our first proposal // Our own proposal: the publicKey, if set, indicates we are a validating
LedgerProposal (const RippleAddress & pubKey, const RippleAddress & privKey, // node but does not indicate if we're validating in this consensus round.
uint256 const& prevLedger, uint256 const& position, std::uint32_t closeTime); LedgerProposal (
RippleAddress const& publicKey,
// an unsigned "dummy" proposal for nodes not validating uint256 const& prevLedger,
LedgerProposal (uint256 const& prevLedger, uint256 const& position, std::uint32_t closeTime); uint256 const& position,
std::uint32_t closeTime);
uint256 getSigningHash () const; uint256 getSigningHash () const;
bool checkSign (std::string const& signature, uint256 const& signingHash); bool checkSign (std::string const& signature) const;
bool checkSign (std::string const& signature)
{
return checkSign (signature, getSigningHash ());
}
bool checkSign ()
{
return checkSign (mSignature, getSigningHash ());
}
NodeID const& getPeerID () const NodeID const& getPeerID () const
{ {
@@ -87,42 +90,23 @@ public:
{ {
return mCloseTime; return mCloseTime;
} }
RippleAddress const& peekPublic () const
{
return mPublicKey;
}
Blob getPubKey () const
{
return mPublicKey.getNodePublic ();
}
Blob sign ();
void setPrevLedger (uint256 const& prevLedger) Blob sign (RippleAddress const& privateKey);
{
mPreviousLedger = prevLedger; bool isPrevLedger (uint256 const& pl) const
}
void setSignature (std::string const& signature)
{
mSignature = signature;
}
bool hasSignature ()
{
return !mSignature.empty ();
}
bool isPrevLedger (uint256 const& pl)
{ {
return mPreviousLedger == pl; return mPreviousLedger == pl;
} }
bool isBowOut () bool isInitial () const
{
return mProposeSeq == seqJoin;
}
bool isBowOut () const
{ {
return mProposeSeq == seqLeave; return mProposeSeq == seqLeave;
} }
std::chrono::steady_clock::time_point getCreateTime () bool isStale (std::chrono::steady_clock::time_point cutoff) const
{
return mTime;
}
bool isStale (std::chrono::steady_clock::time_point cutoff)
{ {
return mTime <= cutoff; return mTime <= cutoff;
} }
@@ -131,7 +115,26 @@ public:
void bowOut (); void bowOut ();
Json::Value getJson () const; 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& proposeHash,
uint256 const& previousLedger, uint256 const& previousLedger,
std::uint32_t proposeSeq, std::uint32_t proposeSeq,
@@ -139,18 +142,6 @@ public:
Blob const& pubKey, Blob const& pubKey,
Blob const& signature); 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 } // ripple
#endif #endif

View File

@@ -88,6 +88,15 @@ int getNextLedgerTimeResolution (
bool previousAgree, bool previousAgree,
std::uint32_t ledgerSeq); 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 // These are protocol parameters used to control the behavior of the system and

View File

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

View File

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

View File

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

View File

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

View File

@@ -179,4 +179,14 @@ int getNextLedgerTimeResolution (
return previousResolution; 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 } // ripple

View File

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

View File

@@ -212,8 +212,8 @@ public:
// ledger proposal/close functions // ledger proposal/close functions
virtual void processTrustedProposal (LedgerProposal::pointer proposal, virtual void processTrustedProposal (LedgerProposal::pointer proposal,
std::shared_ptr<protocol::TMProposeSet> set, RippleAddress nodePublic, std::shared_ptr<protocol::TMProposeSet> set,
uint256 checkLedger, bool sigGood) = 0; RippleAddress const& nodePublic) = 0;
virtual bool recvValidation (STValidation::ref val, virtual bool recvValidation (STValidation::ref val,
std::string const& source) = 0; std::string const& source) = 0;
@@ -255,8 +255,6 @@ public:
virtual bool isAmendmentBlocked () = 0; virtual bool isAmendmentBlocked () = 0;
virtual void setAmendmentBlocked () = 0; virtual void setAmendmentBlocked () = 0;
virtual void consensusViewChange () = 0; virtual void consensusViewChange () = 0;
virtual int getPreviousProposers () = 0;
virtual int getPreviousConvergeTime () = 0;
virtual std::uint32_t getLastCloseTime () = 0; virtual std::uint32_t getLastCloseTime () = 0;
virtual void setLastCloseTime (std::uint32_t t) = 0; virtual void setLastCloseTime (std::uint32_t t) = 0;
@@ -264,6 +262,13 @@ public:
virtual Json::Value getServerInfo (bool human, bool admin) = 0; virtual Json::Value getServerInfo (bool human, bool admin) = 0;
virtual void clearLedgerFetch () = 0; virtual void clearLedgerFetch () = 0;
virtual Json::Value getLedgerFetchInfo () = 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; virtual std::uint32_t acceptLedger () = 0;
using Proposals = hash_map <NodeID, std::deque<LedgerProposal::pointer>>; 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; return;
} }
if (set.has_previousledger () && (set.previousledger ().size () != 32)) if (set.previousledger ().size () != 32)
{ {
p_journal_.warning << "Proposal: malformed"; p_journal_.warning << "Proposal: malformed";
fee_ = Resource::feeInvalidRequest; fee_ = Resource::feeInvalidRequest;
@@ -1139,17 +1139,14 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
uint256 proposeHash, prevLedger; uint256 proposeHash, prevLedger;
memcpy (proposeHash.begin (), set.currenttxhash ().data (), 32); memcpy (proposeHash.begin (), set.currenttxhash ().data (), 32);
if (set.has_previousledger ())
memcpy (prevLedger.begin (), set.previousledger ().data (), 32); memcpy (prevLedger.begin (), set.previousledger ().data (), 32);
uint256 suppression = LedgerProposal::computeSuppressionID ( uint256 suppression = proposalUniqueId (
proposeHash, prevLedger, set.proposeseq(), set.closetime (), proposeHash, prevLedger, set.proposeseq(), set.closetime (),
Blob(set.nodepubkey ().begin (), set.nodepubkey ().end ()), Blob(set.nodepubkey ().begin (), set.nodepubkey ().end ()),
Blob(set.signature ().begin (), set.signature ().end ())); Blob(set.signature ().begin (), set.signature ().end ()));
if (! getApp().getHashRouter ().addSuppressionPeer ( if (! getApp().getHashRouter ().addSuppressionPeer (suppression, id_))
suppression, id_))
{ {
p_journal_.trace << "Proposal: duplicate"; p_journal_.trace << "Proposal: duplicate";
return; return;
@@ -1166,24 +1163,26 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
bool isTrusted = getApp().getUNL ().nodeInUNL (signerPublic); 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)"; p_journal_.debug << "Proposal: Dropping UNTRUSTED (insane)";
return; return;
} }
if (!isTrusted && getApp().getFeeTrack ().isLoadedLocal ()) if (getApp().getFeeTrack ().isLoadedLocal ())
{ {
p_journal_.debug << "Proposal: Dropping UNTRUSTED (load)"; p_journal_.debug << "Proposal: Dropping UNTRUSTED (load)";
return; return;
} }
}
p_journal_.trace << p_journal_.trace <<
"Proposal: " << (isTrusted ? "trusted" : "UNTRUSTED"); "Proposal: " << (isTrusted ? "trusted" : "UNTRUSTED");
LedgerProposal::pointer proposal = std::make_shared<LedgerProposal> ( auto proposal = std::make_shared<LedgerProposal> (
prevLedger.isNonZero () ? prevLedger : uint256(), prevLedger, set.proposeseq (), proposeHash, set.closetime (),
set.proposeseq (), proposeHash, set.closetime (),
signerPublic, suppression); signerPublic, suppression);
getApp().getJobQueue ().addJob (isTrusted ? jtPROPOSAL_t : jtPROPOSAL_ut, getApp().getJobQueue ().addJob (isTrusted ? jtPROPOSAL_t : jtPROPOSAL_ut,
@@ -1695,7 +1694,6 @@ PeerImp::checkPropose (Job& job,
std::shared_ptr <protocol::TMProposeSet> const& packet, std::shared_ptr <protocol::TMProposeSet> const& packet,
LedgerProposal::pointer proposal) LedgerProposal::pointer proposal)
{ {
bool sigGood = false;
bool isTrusted = (job.getType () == jtPROPOSAL_t); bool isTrusted = (job.getType () == jtPROPOSAL_t);
p_journal_.trace << p_journal_.trace <<
@@ -1704,56 +1702,28 @@ PeerImp::checkPropose (Job& job,
assert (packet); assert (packet);
protocol::TMProposeSet& set = *packet; protocol::TMProposeSet& set = *packet;
if (! cluster() && ! proposal->checkSign (set.signature ()))
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 << p_journal_.warning <<
"Proposal with previous ledger fails sig check"; "Proposal fails sig check";
charge (Resource::feeInvalidSignature); charge (Resource::feeInvalidSignature);
return; 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) if (isTrusted)
{ {
getApp().getOPs ().processTrustedProposal ( 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 // relay untrusted proposal
p_journal_.trace << p_journal_.trace <<
@@ -1765,6 +1735,7 @@ PeerImp::checkPropose (Job& job,
p_journal_.debug << p_journal_.debug <<
"Not relaying UNTRUSTED proposal"; "Not relaying UNTRUSTED proposal";
} }
}
} }
void void

View File

@@ -186,7 +186,7 @@ message TMProposeSet
required bytes nodePubKey = 3; required bytes nodePubKey = 3;
required uint32 closeTime = 4; required uint32 closeTime = 4;
required bytes signature = 5; // signature of above fields 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 optional bool checkedSignature = 7; // node vouches signature is correct
repeated bytes addedTransactions = 10; // not required if number is large repeated bytes addedTransactions = 10; // not required if number is large
repeated bytes removedTransactions = 11; // 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 getSigned () const;
Blob getSignature () 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 // The validation this replaced
uint256 const& getPreviousHash () uint256 const& getPreviousHash ()

View File

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

View File

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

View File

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