diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 98c252fd0d..07adb5fac7 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -1394,26 +1394,44 @@ - + True True - + + + True + True + + + True + True + + + True + True + + + + + True + True + True True - + + True + True + + True True - - True - True - @@ -1422,16 +1440,6 @@ - - True - True - - - - - True - True - @@ -1450,10 +1458,6 @@ - - True - True - @@ -1462,10 +1466,6 @@ - - True - True - diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index bb9eadb998..3d4e48f432 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -2115,24 +2115,39 @@ ripple\app\ledger - - ripple\app\ledger + + ripple\app\ledger\impl - - ripple\app\ledger + + ripple\app\ledger\impl + + ripple\app\ledger\impl + + + ripple\app\ledger\impl + + + ripple\app\ledger\impl + + + ripple\app\ledger\impl + + + ripple\app\ledger\impl + ripple\app\ledger\impl - - ripple\app\ledger + + ripple\app\ledger\impl + + + ripple\app\ledger\impl ripple\app\ledger - - ripple\app\ledger - ripple\app\ledger @@ -2142,15 +2157,6 @@ ripple\app\ledger - - ripple\app\ledger - - - ripple\app\ledger - - - ripple\app\ledger - ripple\app\ledger @@ -2172,9 +2178,6 @@ ripple\app\ledger - - ripple\app\ledger - ripple\app\ledger @@ -2184,9 +2187,6 @@ ripple\app\ledger - - ripple\app\ledger - ripple\app\ledger diff --git a/src/ripple/app/ledger/InboundLedger.h b/src/ripple/app/ledger/InboundLedger.h index 802229c95a..4648072d04 100644 --- a/src/ripple/app/ledger/InboundLedger.h +++ b/src/ripple/app/ledger/InboundLedger.h @@ -27,7 +27,6 @@ namespace ripple { -// VFALCO TODO Rename to InboundLedger // A ledger we are trying to acquire class InboundLedger : public PeerSet diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index ac37c2b303..418dfc26bf 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -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 */ diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 126a5b77bc..70197fb477 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -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 () diff --git a/src/ripple/app/ledger/LedgerConsensus.h b/src/ripple/app/ledger/LedgerConsensus.h index 7d26e5f0bd..650bc53a1f 100644 --- a/src/ripple/app/ledger/LedgerConsensus.h +++ b/src/ripple/app/ledger/LedgerConsensus.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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 -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); diff --git a/src/ripple/app/ledger/LedgerProposal.cpp b/src/ripple/app/ledger/LedgerProposal.cpp index d238939a41..26242f3f92 100644 --- a/src/ripple/app/ledger/LedgerProposal.cpp +++ b/src/ripple/app/ledger/LedgerProposal.cpp @@ -26,35 +26,39 @@ 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) +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) { - // 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 (); + 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 ( + RippleAddress const& publicKey, + uint256 const& prevLgr, + uint256 const& position, + std::uint32_t closeTime) + : mPreviousLedger (prevLgr) + , mCurrentHash (position) + , mCloseTime (closeTime) + , mProposeSeq (seqJoin) + , mPublicKey (publicKey) { - mPeerID = mPublicKey.getNodeID (); - mTime = std::chrono::steady_clock::now (); -} + if (mPublicKey.isValid ()) + mPeerID = mPublicKey.getNodeID (); -LedgerProposal::LedgerProposal (uint256 const& prevLgr, uint256 const& position, - std::uint32_t closeTime) : - mPreviousLedger (prevLgr), mCurrentHash (position), mCloseTime (closeTime), mProposeSeq (0) -{ - mTime = std::chrono::steady_clock::now (); + mTime = std::chrono::steady_clock::now (); } uint256 LedgerProposal::getSigningHash () const @@ -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 diff --git a/src/ripple/app/ledger/LedgerProposal.h b/src/ripple/app/ledger/LedgerProposal.h index ee4e1c3f51..4f9f0139d1 100644 --- a/src/ripple/app/ledger/LedgerProposal.h +++ b/src/ripple/app/ledger/LedgerProposal.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -33,35 +33,38 @@ namespace ripple { class LedgerProposal : public CountedObject { +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; 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 diff --git a/src/ripple/app/ledger/LedgerTiming.h b/src/ripple/app/ledger/LedgerTiming.h index e16ddee3a1..c4f37d4d94 100644 --- a/src/ripple/app/ledger/LedgerTiming.h +++ b/src/ripple/app/ledger/LedgerTiming.h @@ -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 diff --git a/src/ripple/app/ledger/DisputedTx.cpp b/src/ripple/app/ledger/impl/DisputedTx.cpp similarity index 99% rename from src/ripple/app/ledger/DisputedTx.cpp rename to src/ripple/app/ledger/impl/DisputedTx.cpp index 62ddf2599e..209b0f28e6 100644 --- a/src/ripple/app/ledger/DisputedTx.cpp +++ b/src/ripple/app/ledger/impl/DisputedTx.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include #include #include #include diff --git a/src/ripple/app/ledger/DisputedTx.h b/src/ripple/app/ledger/impl/DisputedTx.h similarity index 100% rename from src/ripple/app/ledger/DisputedTx.h rename to src/ripple/app/ledger/impl/DisputedTx.h diff --git a/src/ripple/app/ledger/InboundLedger.cpp b/src/ripple/app/ledger/impl/InboundLedger.cpp similarity index 100% rename from src/ripple/app/ledger/InboundLedger.cpp rename to src/ripple/app/ledger/impl/InboundLedger.cpp diff --git a/src/ripple/app/ledger/InboundLedgers.cpp b/src/ripple/app/ledger/impl/InboundLedgers.cpp similarity index 100% rename from src/ripple/app/ledger/InboundLedgers.cpp rename to src/ripple/app/ledger/impl/InboundLedgers.cpp diff --git a/src/ripple/app/ledger/LedgerCleaner.cpp b/src/ripple/app/ledger/impl/LedgerCleaner.cpp similarity index 99% rename from src/ripple/app/ledger/LedgerCleaner.cpp rename to src/ripple/app/ledger/impl/LedgerCleaner.cpp index 2f0068030d..c3df8bd9bf 100644 --- a/src/ripple/app/ledger/LedgerCleaner.cpp +++ b/src/ripple/app/ledger/impl/LedgerCleaner.cpp @@ -18,10 +18,10 @@ //============================================================================== #include -#include #include #include #include +#include #include #include #include diff --git a/src/ripple/app/ledger/LedgerCleaner.h b/src/ripple/app/ledger/impl/LedgerCleaner.h similarity index 100% rename from src/ripple/app/ledger/LedgerCleaner.h rename to src/ripple/app/ledger/impl/LedgerCleaner.h diff --git a/src/ripple/app/ledger/LedgerConsensus.cpp b/src/ripple/app/ledger/impl/LedgerConsensus.cpp similarity index 90% rename from src/ripple/app/ledger/LedgerConsensus.cpp rename to src/ripple/app/ledger/impl/LedgerConsensus.cpp index 0ff9197459..d78c3aa2a8 100644 --- a/src/ripple/app/ledger/LedgerConsensus.cpp +++ b/src/ripple/app/ledger/impl/LedgerConsensus.cpp @@ -18,12 +18,12 @@ //============================================================================== #include -#include #include #include #include #include #include +#include #include #include #include @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -66,6 +65,22 @@ class LedgerConsensusImp , public std::enable_shared_from_this , public CountedObject { +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 prevLCLHash The hash of the Last Closed Ledger (LCL). - @param previousLedger Best guess of what the Last Closed Ledger (LCL) - was. - @param closeTime Closing time point of the LCL. - @param feeVote Our desired fee levels and voting logic. + @param previousProposers the number of participants in the last round + @param previousConvergeTime how long the last round took (ms) + @param inboundTransactions + @param localtx transactions issued by local clients + @param inboundTransactions the set of + @param localtx A set of local transactions to apply + @param prevLCLHash The hash of the Last Closed Ledger (LCL). + @param previousLedger Best guess of what the LCL was. + @param closeTime Closing time point of the LCL. + @param feeVote Our desired fee levels and voting logic. */ - LedgerConsensusImp (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::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 set) { - { - std::lock_guard 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 (false - , *mPreviousLedger); + auto newLCL = std::make_shared (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 - (true, *newLCL); + auto newOL = std::make_shared (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 (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 - (mValPublic, mValPrivate - , initialLedger.getParentHash () - , txSet, mCloseTime); - } - else - { - mOurPosition - = std::make_shared - (initialLedger.getParentHash (), txSet, mCloseTime); - } + mOurPosition = std::make_shared + (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,12 +1725,21 @@ 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; - int mPreviousMSeconds; + + // The time it took for the last consensus process to converge + int mPreviousMSeconds; // Convergence tracking, trusted peers indexed by hash of public key hash_map mPeerPositions; @@ -1771,7 +1755,7 @@ private: std::map mCloseTimes; // nodes that have bowed out of this consensus process - NodeIDSet mDeadNodes; + hash_set mDeadNodes; }; //------------------------------------------------------------------------------ @@ -1781,12 +1765,14 @@ LedgerConsensus::~LedgerConsensus () } std::shared_ptr -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) + std::uint32_t closeTime, FeeVote& feeVote) { - return std::make_shared (localtx, - prevLCLHash, previousLedger, closeTime, feeVote); + return std::make_shared (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. */ diff --git a/src/ripple/app/ledger/LedgerMaster.cpp b/src/ripple/app/ledger/impl/LedgerMaster.cpp similarity index 99% rename from src/ripple/app/ledger/LedgerMaster.cpp rename to src/ripple/app/ledger/impl/LedgerMaster.cpp index 7a812cfd09..374d6ba9e9 100644 --- a/src/ripple/app/ledger/LedgerMaster.cpp +++ b/src/ripple/app/ledger/impl/LedgerMaster.cpp @@ -20,11 +20,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/src/ripple/app/ledger/LedgerTiming.cpp b/src/ripple/app/ledger/impl/LedgerTiming.cpp similarity index 96% rename from src/ripple/app/ledger/LedgerTiming.cpp rename to src/ripple/app/ledger/impl/LedgerTiming.cpp index d7cff8459b..a9342f8784 100644 --- a/src/ripple/app/ledger/LedgerTiming.cpp +++ b/src/ripple/app/ledger/impl/LedgerTiming.cpp @@ -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 diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 3509753845..1aa9915bdf 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -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 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::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; 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 (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 (), - *m_feeVote); + 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 set, RippleAddress nodePublic, - uint256 checkLedger, bool sigGood) + std::shared_ptr 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 ( - 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); diff --git a/src/ripple/app/misc/NetworkOPs.h b/src/ripple/app/misc/NetworkOPs.h index 3898561e27..fc6f0ce979 100644 --- a/src/ripple/app/misc/NetworkOPs.h +++ b/src/ripple/app/misc/NetworkOPs.h @@ -212,8 +212,8 @@ public: // ledger proposal/close functions virtual void processTrustedProposal (LedgerProposal::pointer proposal, - std::shared_ptr set, RippleAddress nodePublic, - uint256 checkLedger, bool sigGood) = 0; + std::shared_ptr 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 >; diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index ef2460fa19..ba65af9dcc 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -1130,7 +1130,7 @@ PeerImp::onMessage (std::shared_ptr 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 const& m) uint256 proposeHash, prevLedger; memcpy (proposeHash.begin (), set.currenttxhash ().data (), 32); + memcpy (prevLedger.begin (), set.previousledger ().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 ())); + 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,25 +1163,27 @@ PeerImp::onMessage (std::shared_ptr const& m) bool isTrusted = getApp().getUNL ().nodeInUNL (signerPublic); - if (!isTrusted && (sanity_.load() == Sanity::insane)) + if (!isTrusted) { - p_journal_.debug << "Proposal: Dropping UNTRUSTED (insane)"; - return; - } + if (sanity_.load() == Sanity::insane) + { + p_journal_.debug << "Proposal: Dropping UNTRUSTED (insane)"; + return; + } - if (!isTrusted && getApp().getFeeTrack ().isLoadedLocal ()) - { - p_journal_.debug << "Proposal: Dropping UNTRUSTED (load)"; - return; + 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 ( - prevLedger.isNonZero () ? prevLedger : uint256(), - set.proposeseq (), proposeHash, set.closetime (), - signerPublic, suppression); + auto proposal = std::make_shared ( + prevLedger, set.proposeseq (), proposeHash, set.closetime (), + signerPublic, suppression); getApp().getJobQueue ().addJob (isTrusted ? jtPROPOSAL_t : jtPROPOSAL_ut, "recvPropose->checkPropose", std::bind(beast::weak_fn( @@ -1695,7 +1694,6 @@ PeerImp::checkPropose (Job& job, std::shared_ptr const& packet, LedgerProposal::pointer proposal) { - bool sigGood = false; bool isTrusted = (job.getType () == jtPROPOSAL_t); p_journal_.trace << @@ -1704,66 +1702,39 @@ PeerImp::checkPropose (Job& job, assert (packet); protocol::TMProposeSet& set = *packet; - - uint256 consensusLCL; - if (! set.has_previousledger() || ! isTrusted) + if (! cluster() && ! proposal->checkSign (set.signature ())) { - std::lock_guard 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"; - 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 ()); - } + p_journal_.warning << + "Proposal fails sig check"; + charge (Resource::feeInvalidSignature); + return; } if (isTrusted) { getApp().getOPs ().processTrustedProposal ( - proposal, packet, publicKey_, prevLedger, sigGood); - } - else if (sigGood && (prevLedger == consensusLCL)) - { - // relay untrusted proposal - p_journal_.trace << - "relaying UNTRUSTED proposal"; - overlay_.relay(set, proposal->getSuppressionID()); + proposal, packet, publicKey_); } else { - p_journal_.debug << - "Not relaying UNTRUSTED proposal"; + uint256 consensusLCL; + { + std::lock_guard lock (getApp().getMasterMutex()); + consensusLCL = getApp().getOPs ().getConsensusLCL (); + } + + if (consensusLCL == proposal->getPrevLedger()) + { + // relay untrusted proposal + p_journal_.trace << + "relaying UNTRUSTED proposal"; + overlay_.relay(set, proposal->getSuppressionID()); + } + else + { + p_journal_.debug << + "Not relaying UNTRUSTED proposal"; + } } } diff --git a/src/ripple/proto/ripple.proto b/src/ripple/proto/ripple.proto index a50314727a..406fd44042 100644 --- a/src/ripple/proto/ripple.proto +++ b/src/ripple/proto/ripple.proto @@ -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 diff --git a/src/ripple/protocol/STValidation.h b/src/ripple/protocol/STValidation.h index fdce28acbe..cd4faef62f 100644 --- a/src/ripple/protocol/STValidation.h +++ b/src/ripple/protocol/STValidation.h @@ -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 () diff --git a/src/ripple/protocol/UintTypes.h b/src/ripple/protocol/UintTypes.h index 8f15c35544..050eb8f794 100644 --- a/src/ripple/protocol/UintTypes.h +++ b/src/ripple/protocol/UintTypes.h @@ -47,7 +47,6 @@ using Currency = base_uint<160, detail::CurrencyTag>; using NodeID = base_uint<160, detail::NodeIDTag>; using CurrencySet = hash_set; -using NodeIDSet = hash_set; /** A special account that's used as the "issuer" for XRP. */ Account const& xrpAccount(); diff --git a/src/ripple/protocol/impl/STValidation.cpp b/src/ripple/protocol/impl/STValidation.cpp index 0a7a4e9b2e..90d0905433 100644 --- a/src/ripple/protocol/impl/STValidation.cpp +++ b/src/ripple/protocol/impl/STValidation.cpp @@ -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 diff --git a/src/ripple/unity/app_ledger.cpp b/src/ripple/unity/app_ledger.cpp index 9b8f674cf0..ac07d6fe4d 100644 --- a/src/ripple/unity/app_ledger.cpp +++ b/src/ripple/unity/app_ledger.cpp @@ -26,22 +26,22 @@ #include #include #include -#include -#include -#include #include -#include -#include #include #include -#include #include -#include #include #include #include +#include +#include +#include +#include +#include #include +#include +#include #include #include