diff --git a/src/AccountState.cpp b/src/AccountState.cpp index b48bcbd131..774e4247db 100644 --- a/src/AccountState.cpp +++ b/src/AccountState.cpp @@ -21,7 +21,7 @@ AccountState::AccountState(const NewcoinAddress& naAccountID) : mAccountID(naAcc mValid = true; } -AccountState::AccountState(const SerializedLedgerEntry::pointer& ledgerEntry, const NewcoinAddress& naAccountID) : +AccountState::AccountState(SLE::ref ledgerEntry, const NewcoinAddress& naAccountID) : mAccountID(naAccountID), mLedgerEntry(ledgerEntry), mValid(false) { if (!mLedgerEntry) diff --git a/src/AccountState.h b/src/AccountState.h index 1a3de87095..5559990a72 100644 --- a/src/AccountState.h +++ b/src/AccountState.h @@ -29,7 +29,7 @@ private: public: AccountState(const NewcoinAddress& naAccountID); // For new accounts - AccountState(const SerializedLedgerEntry::pointer& ledgerEntry,const NewcoinAddress& naAccountI); // For accounts in a ledger + AccountState(SLE::ref ledgerEntry,const NewcoinAddress& naAccountI); // For accounts in a ledger bool bHaveAuthorizedKey() { diff --git a/src/Amount.cpp b/src/Amount.cpp index 3391f470ff..29fd0195be 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -840,8 +840,8 @@ bool STAmount::applyOffer( saTakerPaid = saTakerFunds; // Taker paid all he had. saTakerGot = divide(multiply(saTakerFunds, saOfferPaysAvailable, CURRENCY_ONE, ACCOUNT_ONE), saOfferGetsAvailable, saOfferPays.getCurrency(), saOfferPays.getIssuer()); - Log(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot.getFullText(); - Log(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferPaysAvailable.getFullText(); + Log(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot; + Log(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferPaysAvailable; } return saTakerGot >= saOfferPays; diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp index acceef4887..ed196af6c6 100644 --- a/src/ConnectionPool.cpp +++ b/src/ConnectionPool.cpp @@ -340,7 +340,7 @@ std::vector ConnectionPool::getPeerVector() // Now know peer's node public key. Determine if we want to stay connected. // <-- bNew: false = redundant -bool ConnectionPool::peerConnected(const Peer::pointer& peer, const NewcoinAddress& naPeer, +bool ConnectionPool::peerConnected(Peer::ref peer, const NewcoinAddress& naPeer, const std::string& strIP, int iPort) { bool bNew = false; @@ -399,7 +399,7 @@ bool ConnectionPool::peerConnected(const Peer::pointer& peer, const NewcoinAddre } // We maintain a map of public key to peer for connected and verified peers. Maintain it. -void ConnectionPool::peerDisconnected(const Peer::pointer& peer, const NewcoinAddress& naPeer) +void ConnectionPool::peerDisconnected(Peer::ref peer, const NewcoinAddress& naPeer) { if (naPeer.isValid()) { @@ -486,7 +486,7 @@ bool ConnectionPool::peerScanSet(const std::string& strIp, int iPort) } // --> strIp: not empty -void ConnectionPool::peerClosed(const Peer::pointer& peer, const std::string& strIp, int iPort) +void ConnectionPool::peerClosed(Peer::ref peer, const std::string& strIp, int iPort) { ipPort ipPeer = make_pair(strIp, iPort); bool bScanRefresh = false; @@ -541,7 +541,7 @@ void ConnectionPool::peerClosed(const Peer::pointer& peer, const std::string& st scanRefresh(); } -void ConnectionPool::peerVerified(const Peer::pointer& peer) +void ConnectionPool::peerVerified(Peer::ref peer) { if (mScanning && mScanning == peer) { diff --git a/src/ConnectionPool.h b/src/ConnectionPool.h index b7983b751b..bb13d06436 100644 --- a/src/ConnectionPool.h +++ b/src/ConnectionPool.h @@ -72,16 +72,16 @@ public: // We know peers node public key. // <-- bool: false=reject - bool peerConnected(const Peer::pointer& peer, const NewcoinAddress& naPeer, const std::string& strIP, int iPort); + bool peerConnected(Peer::ref peer, const NewcoinAddress& naPeer, const std::string& strIP, int iPort); // No longer connected. - void peerDisconnected(const Peer::pointer& peer, const NewcoinAddress& naPeer); + void peerDisconnected(Peer::ref peer, const NewcoinAddress& naPeer); // As client accepted. - void peerVerified(const Peer::pointer& peer); + void peerVerified(Peer::ref peer); // As client failed connect and be accepted. - void peerClosed(const Peer::pointer& peer, const std::string& strIp, int iPort); + void peerClosed(Peer::ref peer, const std::string& strIp, int iPort); Json::Value getPeersJson(); std::vector getPeerVector(); diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 245b2c5f78..e968ddf3c0 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -56,7 +56,7 @@ const char *LedgerDBInit[] = { LedgerHash CHARACTER(64), \ NodePubKey CHARACTER(56), \ Flags BIGINT UNSIGNED, \ - CloseTime BIGINT UNSIGNED, \ + SignTime BIGINT UNSIGNED, \ Signature BLOB \ );", "CREATE INDEX ValidationByHash ON \ diff --git a/src/HashedObject.cpp b/src/HashedObject.cpp index fcbbee41bc..f5717e879a 100644 --- a/src/HashedObject.cpp +++ b/src/HashedObject.cpp @@ -23,7 +23,7 @@ bool HashedObjectStore::store(HashedObjectType type, uint32 index, if (mCache.touch(hash)) { #ifdef HS_DEBUG - Log(lsTRACE) << "HOS: " << hash.GetHex() << " store: incache"; + Log(lsTRACE) << "HOS: " << hash << " store: incache"; #endif return false; } @@ -94,7 +94,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) obj = mCache.fetch(hash); if (obj) { - Log(lsTRACE) << "HOS: " << hash.GetHex() << " fetch: incache"; + Log(lsTRACE) << "HOS: " << hash << " fetch: incache"; return obj; } } @@ -113,7 +113,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) if (!db->executeSQL(sql) || !db->startIterRows()) { - Log(lsTRACE) << "HOS: " << hash.GetHex() << " fetch: not in db"; + Log(lsTRACE) << "HOS: " << hash << " fetch: not in db"; return HashedObject::pointer(); } @@ -145,7 +145,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) obj = boost::make_shared(htype, index, data, hash); mCache.canonicalize(hash, obj); } - Log(lsTRACE) << "HOS: " << hash.GetHex() << " fetch: in db"; + Log(lsTRACE) << "HOS: " << hash << " fetch: in db"; return obj; } diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 7895f81b98..08fd23cd7a 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -258,7 +258,7 @@ uint256 Ledger::getHash() return(mHash); } -void Ledger::saveAcceptedLedger(const Ledger::pointer& ledger) +void Ledger::saveAcceptedLedger(Ledger::ref ledger) { static boost::format ledgerExists("SELECT LedgerSeq FROM Ledgers where LedgerSeq = %d;"); static boost::format deleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %d;"); @@ -508,7 +508,7 @@ void Ledger::setCloseTime(boost::posix_time::ptime ptm) } // XXX Use shared locks where possible? -LedgerStateParms Ledger::writeBack(LedgerStateParms parms, const SLE::pointer& entry) +LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::ref entry) { ScopedLock l(mAccountStateMap->Lock()); bool create = false; diff --git a/src/Ledger.h b/src/Ledger.h index dd8a770805..c671a57bf2 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -41,7 +41,8 @@ class Ledger : public boost::enable_shared_from_this { // The basic Ledger structure, can be opened, closed, or synching friend class TransactionEngine; public: - typedef boost::shared_ptr pointer; + typedef boost::shared_ptr pointer; + typedef const boost::shared_ptr& ref; enum TransResult { @@ -156,12 +157,12 @@ public: // high-level functions AccountState::pointer getAccountState(const NewcoinAddress& acctID); - LedgerStateParms writeBack(LedgerStateParms parms, const SLE::pointer&); + LedgerStateParms writeBack(LedgerStateParms parms, SLE::ref); SLE::pointer getAccountRoot(const uint160& accountID); SLE::pointer getAccountRoot(const NewcoinAddress& naAccountID); // database functions - static void saveAcceptedLedger(const Ledger::pointer&); + static void saveAcceptedLedger(Ledger::ref); static Ledger::pointer loadByIndex(uint32 ledgerIndex); static Ledger::pointer loadByHash(const uint256& ledgerHash); diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index 949cc7e851..177dfa6dd6 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -20,7 +20,7 @@ PeerSet::PeerSet(const uint256& hash, int interval) : mHash(hash), mTimerInterva assert((mTimerInterval > 10) && (mTimerInterval < 30000)); } -void PeerSet::peerHas(const Peer::pointer& ptr) +void PeerSet::peerHas(Peer::ref ptr) { boost::recursive_mutex::scoped_lock sl(mLock); std::vector< boost::weak_ptr >::iterator it = mPeers.begin(); @@ -40,7 +40,7 @@ void PeerSet::peerHas(const Peer::pointer& ptr) newPeer(ptr); } -void PeerSet::badPeer(const Peer::pointer& ptr) +void PeerSet::badPeer(Peer::ref ptr) { boost::recursive_mutex::scoped_lock sl(mLock); std::vector< boost::weak_ptr >::iterator it = mPeers.begin(); @@ -72,7 +72,7 @@ void PeerSet::invokeOnTimer() if (!mProgress) { ++mTimeouts; - Log(lsWARNING) << "Timeout " << mTimeouts << " acquiring " << mHash.GetHex(); + Log(lsWARNING) << "Timeout " << mTimeouts << " acquiring " << mHash; } else mProgress = false; @@ -93,7 +93,7 @@ LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE mHaveBase(false), mHaveState(false), mHaveTransactions(false), mAborted(false), mSignaled(false) { #ifdef LA_DEBUG - Log(lsTRACE) << "Acquiring ledger " << mHash.GetHex(); + Log(lsTRACE) << "Acquiring ledger " << mHash; #endif } @@ -118,7 +118,7 @@ void LedgerAcquire::done() return; mSignaled = true; #ifdef LA_DEBUG - Log(lsTRACE) << "Done acquiring ledger " << mHash.GetHex(); + Log(lsTRACE) << "Done acquiring ledger " << mHash; #endif std::vector< boost::function > triggers; @@ -142,13 +142,13 @@ void LedgerAcquire::addOnComplete(boost::function mLock.unlock(); } -void LedgerAcquire::trigger(const Peer::pointer& peer, bool timer) +void LedgerAcquire::trigger(Peer::ref peer, bool timer) { if (mAborted || mComplete || mFailed) return; #ifdef LA_DEBUG - if(peer) Log(lsTRACE) << "Trigger acquiring ledger " << mHash.GetHex() << " from " << peer->getIP(); - else Log(lsTRACE) << "Trigger acquiring ledger " << mHash.GetHex(); + if(peer) Log(lsTRACE) << "Trigger acquiring ledger " << mHash << " from " << peer->getIP(); + else Log(lsTRACE) << "Trigger acquiring ledger " << mHash; if (mComplete || mFailed) Log(lsTRACE) << "complete=" << mComplete << " failed=" << mFailed; else @@ -257,7 +257,7 @@ void LedgerAcquire::trigger(const Peer::pointer& peer, bool timer) resetTimer(); } -void PeerSet::sendRequest(const newcoin::TMGetLedger& tmGL, const Peer::pointer& peer) +void PeerSet::sendRequest(const newcoin::TMGetLedger& tmGL, Peer::ref peer) { if (!peer) sendRequest(tmGL); @@ -290,7 +290,7 @@ void PeerSet::sendRequest(const newcoin::TMGetLedger& tmGL) bool LedgerAcquire::takeBase(const std::string& data) { // Return value: true=normal, false=bad data #ifdef LA_DEBUG - Log(lsTRACE) << "got base acquiring ledger " << mHash.GetHex(); + Log(lsTRACE) << "got base acquiring ledger " << mHash; #endif boost::recursive_mutex::scoped_lock sl(mLock); if (mHaveBase) return true; @@ -298,7 +298,7 @@ bool LedgerAcquire::takeBase(const std::string& data) if (mLedger->getHash() != mHash) { Log(lsWARNING) << "Acquire hash mismatch"; - Log(lsWARNING) << mLedger->getHash().GetHex() << "!=" << mHash.GetHex(); + Log(lsWARNING) << mLedger->getHash() << "!=" << mHash; mLedger = Ledger::pointer(); #ifdef TRUST_NETWORK assert(false); @@ -357,7 +357,7 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs, const std::list< std::vector >& data) { #ifdef LA_DEBUG - Log(lsTRACE) << "got ASdata acquiring ledger " << mHash.GetHex(); + Log(lsTRACE) << "got ASdata acquiring ledger " << mHash; #endif if (!mHaveBase) return false; std::list::const_iterator nodeIDit = nodeIDs.begin(); @@ -431,11 +431,11 @@ bool LedgerAcquireMaster::hasLedger(const uint256& hash) void LedgerAcquireMaster::dropLedger(const uint256& hash) { assert(hash.isNonZero()); - boost::mutex::scoped_lock sl(mLock); + boost::mutex::scoped_lock sl(mLock); mLedgers.erase(hash); } -bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, const Peer::pointer& peer) +bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::ref peer) { #ifdef LA_DEBUG Log(lsTRACE) << "got data for acquiring ledger "; @@ -448,7 +448,7 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, const Pee } memcpy(hash.begin(), packet.ledgerhash().data(), 32); #ifdef LA_DEBUG - Log(lsTRACE) << hash.GetHex(); + Log(lsTRACE) << hash; #endif LedgerAcquire::pointer ledger = find(hash); diff --git a/src/LedgerAcquire.h b/src/LedgerAcquire.h index ff92ad4ef8..6781eddf88 100644 --- a/src/LedgerAcquire.h +++ b/src/LedgerAcquire.h @@ -31,7 +31,7 @@ protected: virtual ~PeerSet() { ; } void sendRequest(const newcoin::TMGetLedger& message); - void sendRequest(const newcoin::TMGetLedger& message, const Peer::pointer& peer); + void sendRequest(const newcoin::TMGetLedger& message, Peer::ref peer); public: const uint256& getHash() const { return mHash; } @@ -41,12 +41,12 @@ public: void progress() { mProgress = true; } - void peerHas(const Peer::pointer&); - void badPeer(const Peer::pointer&); + void peerHas(Peer::ref); + void badPeer(Peer::ref); void resetTimer(); protected: - virtual void newPeer(const Peer::pointer&) = 0; + virtual void newPeer(Peer::ref) = 0; virtual void onTimer(void) = 0; virtual boost::weak_ptr pmDowncast() = 0; @@ -72,7 +72,7 @@ protected: void done(); void onTimer(); - void newPeer(const Peer::pointer& peer) { trigger(peer, false); } + void newPeer(Peer::ref peer) { trigger(peer, false); } boost::weak_ptr pmDowncast(); @@ -92,7 +92,7 @@ public: bool takeTxRootNode(const std::vector& data); bool takeAsNode(const std::list& IDs, const std::list >& data); bool takeAsRootNode(const std::vector& data); - void trigger(const Peer::pointer&, bool timer); + void trigger(Peer::ref, bool timer); }; class LedgerAcquireMaster @@ -108,7 +108,7 @@ public: LedgerAcquire::pointer find(const uint256& hash); bool hasLedger(const uint256& ledgerHash); void dropLedger(const uint256& ledgerHash); - bool gotLedgerData(newcoin::TMLedgerData& packet, const Peer::pointer&); + bool gotLedgerData(newcoin::TMLedgerData& packet, Peer::ref); }; #endif diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 980e0be376..fa94f5630b 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -33,7 +33,7 @@ void TransactionAcquire::done() { if (mFailed) { - Log(lsWARNING) << "Failed to acqiure TXs " << mHash.GetHex(); + Log(lsWARNING) << "Failed to acqiure TXs " << mHash; theApp->getOPs().mapComplete(mHash, SHAMap::pointer()); } else @@ -45,7 +45,7 @@ boost::weak_ptr TransactionAcquire::pmDowncast() return boost::shared_polymorphic_downcast(shared_from_this()); } -void TransactionAcquire::trigger(const Peer::pointer& peer, bool timer) +void TransactionAcquire::trigger(Peer::ref peer, bool timer) { if (mComplete || mFailed) return; @@ -87,7 +87,7 @@ void TransactionAcquire::trigger(const Peer::pointer& peer, bool timer) } bool TransactionAcquire::takeNodes(const std::list& nodeIDs, - const std::list< std::vector >& data, const Peer::pointer& peer) + const std::list< std::vector >& data, Peer::ref peer) { if (mComplete) return true; @@ -136,31 +136,44 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes) { // new vote if (votesYes) { - Log(lsTRACE) << "Peer " << peer.GetHex() << " votes YES on " << mTransactionID.GetHex(); + Log(lsTRACE) << "Peer " << peer << " votes YES on " << mTransactionID; ++mYays; } else { - Log(lsTRACE) << "Peer " << peer.GetHex() << " votes NO on " << mTransactionID.GetHex(); + Log(lsTRACE) << "Peer " << peer << " votes NO on " << mTransactionID; ++mNays; } } else if (votesYes && !res.first->second) { // changes vote to yes - Log(lsTRACE) << "Peer " << peer.GetHex() << " now votes YES on " << mTransactionID.GetHex(); + Log(lsTRACE) << "Peer " << peer << " now votes YES on " << mTransactionID; --mNays; ++mYays; res.first->second = true; } else if (!votesYes && res.first->second) { // changes vote to no - Log(lsTRACE) << "Peer " << peer.GetHex() << " now votes NO on " << mTransactionID.GetHex(); + Log(lsTRACE) << "Peer " << peer << " now votes NO on " << mTransactionID; ++mNays; --mYays; res.first->second = false; } } +void LCTransaction::unVote(const uint160& peer) +{ + boost::unordered_map::iterator it = mVotes.find(peer); + if (it != mVotes.end()) + { + if (it->second) + --mYays; + else + --mNays; + mVotes.erase(it); + } +} + bool LCTransaction::updatePosition(int percentTime, bool proposing) { // this many seconds after close, should our position change if (mOurPosition && (mNays == 0)) @@ -191,19 +204,19 @@ bool LCTransaction::updatePosition(int percentTime, bool proposing) return false; } mOurPosition = newPosition; - Log(lsTRACE) << "We now vote " << (mOurPosition ? "YES" : "NO") << " on " << mTransactionID.GetHex(); + Log(lsTRACE) << "We now vote " << (mOurPosition ? "YES" : "NO") << " on " << mTransactionID; return true; } -LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, const Ledger::pointer& previousLedger, uint32 closeTime) - : mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger), - mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false) +LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previousLedger, uint32 closeTime) + : mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), + mPreviousLedger(previousLedger), mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false) { mValSeed = theConfig.VALIDATION_SEED; mConsensusStartTime = boost::posix_time::microsec_clock::universal_time(); Log(lsDEBUG) << "Creating consensus object"; - Log(lsTRACE) << "LCL:" << previousLedger->getHash().GetHex() <<", ct=" << closeTime; + Log(lsTRACE) << "LCL:" << previousLedger->getHash() <<", ct=" << closeTime; mPreviousProposers = theApp->getOPs().getPreviousProposers(); mPreviousMSeconds = theApp->getOPs().getPreviousConvergeTime(); assert(mPreviousMSeconds); @@ -226,8 +239,8 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, const Ledger::point handleLCL(prevLCLHash); if (!mHaveCorrectLCL) { - Log(lsINFO) << "Entering consensus with: " << previousLedger->getHash().GetHex(); - Log(lsINFO) << "Correct LCL is: " << prevLCLHash.GetHex(); + Log(lsINFO) << "Entering consensus with: " << previousLedger->getHash(); + Log(lsINFO) << "Correct LCL is: " << prevLCLHash; } } @@ -251,6 +264,7 @@ void LedgerConsensus::checkLCL() if (netLgr != mPrevLedgerHash) { // LCL change Log(lsWARNING) << "View of consensus changed during consensus (" << netLgrCount << ")"; + Log(lsWARNING) << mPrevLedgerHash << " to " << netLgr; if (mHaveCorrectLCL) theApp->getOPs().consensusViewChange(); handleLCL(netLgr); @@ -270,11 +284,11 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) return; else { - Log(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash.GetHex(); + Log(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash; mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(mPrevLedgerHash); std::vector peerList = theApp->getConnectionPool().getPeerVector(); bool found = false; - BOOST_FOREACH(Peer::pointer& peer, peerList) + BOOST_FOREACH(Peer::ref peer, peerList) { if (peer->hasLedger(mPrevLedgerHash)) { @@ -284,16 +298,19 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) } if (!found) { - BOOST_FOREACH(Peer::pointer& peer, peerList) + BOOST_FOREACH(Peer::ref peer, peerList) mAcquiringLedger->peerHas(peer); } mHaveCorrectLCL = false; mProposing = false; mValidating = false; + mCloseTimes.clear(); + mPeerPositions.clear(); + mDisputes.clear(); return; } - Log(lsINFO) << "Acquired the consensus ledger " << mPrevLedgerHash.GetHex(); + Log(lsINFO) << "Acquired the consensus ledger " << mPrevLedgerHash; mHaveCorrectLCL = true; mAcquiringLedger = LedgerAcquire::pointer(); mCloseResolution = ContinuousLedgerTiming::getNextLedgerTimeResolution( @@ -306,6 +323,7 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger) { SHAMap::pointer initialSet = initialLedger.peekTransactionMap()->snapShot(false); uint256 txSet = initialSet->getHash(); + Log(lsINFO) << "initial position " << txSet; // if any peers have taken a contrary position, process disputes boost::unordered_set found; @@ -327,7 +345,7 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger) mOurPosition = boost::make_shared(initialLedger.getParentHash(), txSet, mCloseTime); mapComplete(txSet, initialSet, false); if (mProposing) - propose(std::vector(), std::vector()); + propose(); } void LedgerConsensus::createDisputes(const SHAMap::pointer& m1, const SHAMap::pointer& m2) @@ -353,7 +371,7 @@ void LedgerConsensus::createDisputes(const SHAMap::pointer& m1, const SHAMap::po void LedgerConsensus::mapComplete(const uint256& hash, const SHAMap::pointer& map, bool acquired) { if (acquired) - Log(lsINFO) << "We have acquired TXS " << hash.GetHex(); + Log(lsINFO) << "We have acquired TXS " << hash; mAcquiring.erase(hash); if (!map) @@ -388,7 +406,7 @@ void LedgerConsensus::mapComplete(const uint256& hash, const SHAMap::pointer& ma if (!peers.empty()) adjustCount(map, peers); else if (acquired) - Log(lsWARNING) << "By the time we got the map " << hash.GetHex() << " no peers were proposing it"; + Log(lsWARNING) << "By the time we got the map " << hash << " no peers were proposing it"; sendHaveTxSet(hash, true); } @@ -442,25 +460,24 @@ void LedgerConsensus::statePreClose() // This ledger is open. This computes how long since the last ledger closed int sinceClose; - int ledgerInterval = 0; + int idleInterval = 0; if (mHaveCorrectLCL && mPreviousLedger->getCloseAgree()) { // we can use consensus timing sinceClose = 1000 * (theApp->getOPs().getCloseTimeNC() - mPreviousLedger->getCloseTimeNC()); - ledgerInterval = 2 * mPreviousLedger->getCloseResolution(); - if (ledgerInterval < LEDGER_IDLE_INTERVAL) - ledgerInterval = LEDGER_IDLE_INTERVAL; + idleInterval = 2 * mPreviousLedger->getCloseResolution(); + if (idleInterval < LEDGER_IDLE_INTERVAL) + idleInterval = LEDGER_IDLE_INTERVAL; } else { sinceClose = theApp->getOPs().getLastCloseTime(); - ledgerInterval = LEDGER_IDLE_INTERVAL; + idleInterval = LEDGER_IDLE_INTERVAL; } - if (sinceClose >= ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed, - mPreviousMSeconds, sinceClose, ledgerInterval)) + if (ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed, + mPreviousMSeconds, sinceClose, idleInterval)) { // it is time to close the ledger - Log(lsINFO) << "CLC: closing ledger"; mState = lcsESTABLISH; mConsensusStartTime = boost::posix_time::microsec_clock::universal_time(); mCloseTime = theApp->getOPs().getCloseTimeNC(); @@ -484,7 +501,7 @@ void LedgerConsensus::stateEstablish() } if (haveConsensus()) { - Log(lsINFO) << "Converge cutoff"; + Log(lsINFO) << "Converge cutoff (" << mPeerPositions.size() << " participants)"; mState = lcsFINISHED; beginAccept(); } @@ -503,7 +520,7 @@ void LedgerConsensus::stateAccepted() void LedgerConsensus::timerEntry() { - if (!mHaveCorrectLCL) + if ((!mHaveCorrectLCL) || (mState == lcsPRE_CLOSE)) checkLCL(); mCurrentMSeconds = @@ -512,7 +529,7 @@ void LedgerConsensus::timerEntry() switch (mState) { - case lcsPRE_CLOSE: statePreClose(); if (mState != lcsESTABLISH) return; fallthru(); + case lcsPRE_CLOSE: statePreClose(); return; case lcsESTABLISH: stateEstablish(); if (mState != lcsFINISHED) return; fallthru(); case lcsFINISHED: stateFinished(); if (mState != lcsACCEPTED) return; fallthru(); case lcsACCEPTED: stateAccepted(); return; @@ -522,9 +539,34 @@ void LedgerConsensus::timerEntry() void LedgerConsensus::updateOurPositions() { + boost::posix_time::ptime peerCutoff = boost::posix_time::second_clock::universal_time(); + boost::posix_time::ptime ourCutoff = peerCutoff - boost::posix_time::seconds(PROPOSE_INTERVAL); + peerCutoff -= boost::posix_time::seconds(PROPOSE_FRESHNESS); + bool changes = false; SHAMap::pointer ourPosition; - std::vector addedTx, removedTx; +// std::vector addedTx, removedTx; + + // Verify freshness of peer positions and compute close times + std::map closeTimes; + boost::unordered_map::iterator + it = mPeerPositions.begin(), end = mPeerPositions.end(); + while (it != end) + { + if (it->second->isStale(peerCutoff)) + { // proposal is stale + uint160 peerID = it->second->getPeerID(); + Log(lsWARNING) << "Removing stale proposal from " << peerID; + BOOST_FOREACH(u256_lct_pair& it, mDisputes) + it.second->unVote(peerID); + mPeerPositions.erase(it++); + } + else + { // proposal is still fresh + ++closeTimes[roundCloseTime(it->second->getCloseTime())]; + ++it; + } + } BOOST_FOREACH(u256_lct_pair& it, mDisputes) { @@ -538,20 +580,16 @@ void LedgerConsensus::updateOurPositions() if (it.second->getOurPosition()) // now a yes { ourPosition->addItem(SHAMapItem(it.first, it.second->peekTransaction()), true, false); - addedTx.push_back(it.first); +// addedTx.push_back(it.first); } else // now a no { ourPosition->delItem(it.first); - removedTx.push_back(it.first); +// removedTx.push_back(it.first); } } } - std::map closeTimes; - - BOOST_FOREACH(u160_prop_pair& it, mPeerPositions) - ++closeTimes[it.second->getCloseTime() - (it.second->getCloseTime() % mCloseResolution)]; int neededWeight; if (mClosePercent < AV_MID_CONSENSUS_TIME) @@ -567,13 +605,13 @@ void LedgerConsensus::updateOurPositions() if (thresh == 0) { // no other times mHaveCloseTimeConsensus = true; - closeTime = mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution); + closeTime = roundCloseTime(mOurPosition->getCloseTime()); } else { if (mProposing) { - ++closeTimes[mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution)]; + ++closeTimes[roundCloseTime(mOurPosition->getCloseTime())]; ++thresh; } thresh = thresh * neededWeight / 100; @@ -593,13 +631,12 @@ void LedgerConsensus::updateOurPositions() } } - if (closeTime != (mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution))) - { - if (!changes) - { - ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true); - changes = true; - } + if ((!changes) && + ((closeTime != (roundCloseTime(mOurPosition->getCloseTime()))) || + (mOurPosition->isStale(ourCutoff)))) + { // close time changed or our position is stale + ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true); + changes = true; } if (changes) @@ -607,9 +644,9 @@ void LedgerConsensus::updateOurPositions() uint256 newHash = ourPosition->getHash(); mOurPosition->changePosition(newHash, closeTime); if (mProposing) - propose(addedTx, removedTx); + propose(); mapComplete(newHash, ourPosition, false); - Log(lsINFO) << "Position change: CTime " << closeTime << ", tx " << newHash.GetHex(); + Log(lsINFO) << "Position change: CTime " << closeTime << ", tx " << newHash; } } @@ -691,9 +728,9 @@ void LedgerConsensus::startAcquiring(const TransactionAcquire::pointer& acquire) acquire->resetTimer(); } -void LedgerConsensus::propose(const std::vector& added, const std::vector& removed) +void LedgerConsensus::propose() { - Log(lsTRACE) << "We propose: " << mOurPosition->getCurrentHash().GetHex(); + Log(lsTRACE) << "We propose: " << mOurPosition->getCurrentHash(); newcoin::TMProposeSet prop; prop.set_currenttxhash(mOurPosition->getCurrentHash().begin(), 256 / 8); prop.set_proposeseq(mOurPosition->getProposeSeq()); @@ -709,7 +746,7 @@ void LedgerConsensus::propose(const std::vector& added, const std::vect void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vector& tx) { - Log(lsTRACE) << "Transaction " << txID.GetHex() << " is disputed"; + Log(lsTRACE) << "Transaction " << txID << " is disputed"; boost::unordered_map::iterator it = mDisputes.find(txID); if (it != mDisputes.end()) return; @@ -751,8 +788,7 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition) ++mCloseTimes[newPosition->getCloseTime()]; } - Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" - << newPosition->getCurrentHash().GetHex(); + Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" << newPosition->getCurrentHash(); currentPosition = newPosition; SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true); if (set) @@ -766,7 +802,7 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition) return true; } -bool LedgerConsensus::peerHasSet(const Peer::pointer& peer, const uint256& hashSet, newcoin::TxSetStatus status) +bool LedgerConsensus::peerHasSet(Peer::ref peer, const uint256& hashSet, newcoin::TxSetStatus status) { if (status != newcoin::tsHAVE) // Indirect requests are for future support return true; @@ -783,7 +819,7 @@ bool LedgerConsensus::peerHasSet(const Peer::pointer& peer, const uint256& hashS return true; } -bool LedgerConsensus::peerGaveNodes(const Peer::pointer& peer, const uint256& setHash, +bool LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash, const std::list& nodeIDs, const std::list< std::vector >& nodeData) { boost::unordered_map::iterator acq = mAcquiring.find(setHash); @@ -813,33 +849,36 @@ void LedgerConsensus::Saccept(boost::shared_ptr This, SHAMap::p void LedgerConsensus::deferProposal(const LedgerProposal::pointer& proposal, const NewcoinAddress& peerPublic) { - if (!peerPublic.isValid()) - return; std::list& props = mDeferredProposals[peerPublic.getNodeID()]; - if (props.size() > (mPreviousProposers + 10)) + if (props.size() >= (mPreviousProposers + 10)) props.pop_front(); props.push_back(proposal); } void LedgerConsensus::playbackProposals() { - for ( boost::unordered_map< uint160, std::list >::iterator + for (boost::unordered_map< uint160, std::list >::iterator it = mDeferredProposals.begin(), end = mDeferredProposals.end(); it != end; ++it) { BOOST_FOREACH(const LedgerProposal::pointer& proposal, it->second) { - proposal->setPrevLedger(mPrevLedgerHash); - if (proposal->checkSign()) - { - Log(lsINFO) << "Applying deferred proposal"; - peerPosition(proposal); + if (proposal->hasSignature()) + { // old-style + proposal->setPrevLedger(mPrevLedgerHash); + if (proposal->checkSign()) + { + Log(lsINFO) << "Applying deferred proposal"; + peerPosition(proposal); + } } + else if (proposal->isPrevLedger(mPrevLedgerHash)) + peerPosition(proposal); } } } void LedgerConsensus::applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn, - const Ledger::pointer& ledger, CanonicalTXSet& failedTransactions, bool openLedger) + Ledger::ref ledger, CanonicalTXSet& failedTransactions, bool openLedger) { TransactionEngineParams parms = openLedger ? tapOPEN_LEDGER : tapNONE; #ifndef TRUST_NETWORK @@ -871,8 +910,8 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, const Serializ #endif } -void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, const Ledger::pointer& applyLedger, - const Ledger::pointer& checkLedger, CanonicalTXSet& failedTransactions, bool openLgr) +void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, Ledger::ref applyLedger, + Ledger::ref checkLedger, CanonicalTXSet& failedTransactions, bool openLgr) { TransactionEngineParams parms = openLgr ? tapOPEN_LEDGER : tapNONE; TransactionEngine engine(applyLedger); @@ -881,7 +920,7 @@ void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, const Ledger { if (!checkLedger->hasTransaction(item->getTag())) { - Log(lsINFO) << "Processing candidate transaction: " << item->getTag().GetHex(); + Log(lsINFO) << "Processing candidate transaction: " << item->getTag(); #ifndef TRUST_NETWORK try { @@ -928,18 +967,22 @@ void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, const Ledger } while (successes > 0); } +uint32 LedgerConsensus::roundCloseTime(uint32 closeTime) +{ + return closeTime - (closeTime % mCloseResolution); +} + void LedgerConsensus::accept(const SHAMap::pointer& set) { assert(set->getHash() == mOurPosition->getCurrentHash()); - uint32 closeTime = mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() & mCloseResolution); + uint32 closeTime = roundCloseTime(mOurPosition->getCloseTime()); Log(lsINFO) << "Computing new LCL based on network consensus"; if (mHaveCorrectLCL) { - Log(lsINFO) << "CNF tx " << mOurPosition->getCurrentHash().GetHex() << ", close " << closeTime; - Log(lsINFO) << "CNF mode " << theApp->getOPs().getOperatingMode() - << ", oldLCL " << mPrevLedgerHash.GetHex(); + Log(lsINFO) << "CNF tx " << mOurPosition->getCurrentHash() << ", close " << closeTime; + Log(lsINFO) << "CNF mode " << theApp->getOPs().getOperatingMode() << ", oldLCL " << mPrevLedgerHash; } Ledger::pointer newLCL = boost::make_shared(false, boost::ref(*mPreviousLedger)); @@ -964,9 +1007,9 @@ void LedgerConsensus::accept(const SHAMap::pointer& set) if (mValidating) { SerializedValidation::pointer v = boost::make_shared - (newLCLHash, newLCL->getCloseTimeNC(), mValSeed, mProposing); + (newLCLHash, theApp->getOPs().getValidationTimeNC(), mValSeed, mProposing); v->setTrusted(); - Log(lsINFO) << "CNF Val " << newLCLHash.GetHex(); + Log(lsINFO) << "CNF Val " << newLCLHash; theApp->getValidations().addValidation(v); std::vector validation = v->getSigned(); newcoin::TMValidation val; @@ -974,7 +1017,7 @@ void LedgerConsensus::accept(const SHAMap::pointer& set) theApp->getConnectionPool().relayMessage(NULL, boost::make_shared(val, newcoin::mtVALIDATION)); } else - Log(lsINFO) << "CNF newLCL " << newLCLHash.GetHex(); + Log(lsINFO) << "CNF newLCL " << newLCLHash; Ledger::pointer newOL = boost::make_shared(true, boost::ref(*newLCL)); ScopedLock sl = theApp->getMasterLedger().getLock(); @@ -1007,14 +1050,13 @@ void LedgerConsensus::accept(const SHAMap::pointer& set) mState = lcsACCEPTED; sl.unlock(); - if (mValidating && mOurPosition->getCurrentHash().isNonZero()) + if (mValidating) { // see how close our close time is to other node's close time reports Log(lsINFO) << "We closed at " << boost::lexical_cast(mCloseTime); uint64 closeTotal = mCloseTime; int closeCount = 1; - for (std::map::iterator it = mCloseTimes.begin(), end = - mCloseTimes.end(); it != end; ++it) - { + for (std::map::iterator it = mCloseTimes.begin(), end = mCloseTimes.end(); it != end; ++it) + { // FIXME: Use median, not average Log(lsINFO) << boost::lexical_cast(it->second) << " time votes for " << boost::lexical_cast(it->first); closeCount += it->second; @@ -1024,6 +1066,7 @@ void LedgerConsensus::accept(const SHAMap::pointer& set) closeTotal /= closeCount; int offset = static_cast(closeTotal) - static_cast(mCloseTime); Log(lsINFO) << "Our close offset is estimated at " << offset << " (" << closeCount << ")"; + theApp->getOPs().closeTimeOffset(offset); } #ifdef DEBUG diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 31ffdf06c9..eef08c8807 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -27,11 +27,11 @@ protected: SHAMap::pointer mMap; bool mHaveRoot; - void onTimer() { trigger(Peer::pointer(), true); } - void newPeer(const Peer::pointer& peer) { trigger(peer, false); } + void onTimer() { trigger(Peer::pointer(), true); } + void newPeer(Peer::ref peer) { trigger(peer, false); } void done(); - void trigger(const Peer::pointer&, bool timer); + void trigger(Peer::ref, bool timer); boost::weak_ptr pmDowncast(); public: @@ -41,7 +41,7 @@ public: SHAMap::pointer getMap() { return mMap; } bool takeNodes(const std::list& IDs, const std::list< std::vector >& data, - const Peer::pointer&); + Peer::ref); }; class LCTransaction @@ -64,6 +64,7 @@ public: Serializer& peekTransaction() { return transaction; } void setVote(const uint160& peer, bool votesYes); + void unVote(const uint160& peer); bool updatePosition(int percentTime, bool proposing); }; @@ -118,22 +119,24 @@ protected: static void Saccept(boost::shared_ptr This, SHAMap::pointer txSet); void accept(const SHAMap::pointer& txSet); - void weHave(const uint256& id, const Peer::pointer& avoidPeer); + void weHave(const uint256& id, Peer::ref avoidPeer); void startAcquiring(const TransactionAcquire::pointer&); SHAMap::pointer find(const uint256& hash); void createDisputes(const SHAMap::pointer&, const SHAMap::pointer&); void addDisputedTransaction(const uint256&, const std::vector& transaction); void adjustCount(const SHAMap::pointer& map, const std::vector& peers); - void propose(const std::vector& addedTx, const std::vector& removedTx); + void propose(); void addPosition(LedgerProposal&, bool ours); void removePosition(LedgerProposal&, bool ours); void sendHaveTxSet(const uint256& set, bool direct); - void applyTransactions(const SHAMap::pointer& transactionSet, const Ledger::pointer& targetLedger, - const Ledger::pointer& checkLedger, CanonicalTXSet& failedTransactions, bool openLgr); + void applyTransactions(const SHAMap::pointer& transactionSet, Ledger::ref targetLedger, + Ledger::ref checkLedger, CanonicalTXSet& failedTransactions, bool openLgr); void applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn, - const Ledger::pointer& targetLedger, CanonicalTXSet& failedTransactions, bool openLgr); + Ledger::ref targetLedger, CanonicalTXSet& failedTransactions, bool openLgr); + + uint32 roundCloseTime(uint32 closeTime); // manipulating our own position void statusChange(newcoin::NodeEvent, Ledger& ledger); @@ -141,11 +144,12 @@ protected: void updateOurPositions(); void playbackProposals(); int getThreshold(); + void beginAccept(); void endConsensus(); public: - LedgerConsensus(const uint256& prevLCLHash, const Ledger::pointer& previousLedger, uint32 closeTime); + LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previousLedger, uint32 closeTime); int startup(); Json::Value getJson(); @@ -173,9 +177,9 @@ public: bool peerPosition(const LedgerProposal::pointer&); void deferProposal(const LedgerProposal::pointer& proposal, const NewcoinAddress& peerPublic); - bool peerHasSet(const Peer::pointer& peer, const uint256& set, newcoin::TxSetStatus status); + bool peerHasSet(Peer::ref peer, const uint256& set, newcoin::TxSetStatus status); - bool peerGaveNodes(const Peer::pointer& peer, const uint256& setHash, + bool peerGaveNodes(Peer::ref peer, const uint256& setHash, const std::list& nodeIDs, const std::list< std::vector >& nodeData); }; diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index 7015a7b76f..2f31478bd2 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -61,7 +61,7 @@ LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const return it->second.mAction; } -void LedgerEntrySet::entryCache(const SLE::pointer& sle) +void LedgerEntrySet::entryCache(SLE::ref sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -82,7 +82,7 @@ void LedgerEntrySet::entryCache(const SLE::pointer& sle) } } -void LedgerEntrySet::entryCreate(const SLE::pointer& sle) +void LedgerEntrySet::entryCreate(SLE::ref sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -112,7 +112,7 @@ void LedgerEntrySet::entryCreate(const SLE::pointer& sle) } } -void LedgerEntrySet::entryModify(const SLE::pointer& sle) +void LedgerEntrySet::entryModify(SLE::ref sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -147,7 +147,7 @@ void LedgerEntrySet::entryModify(const SLE::pointer& sle) } } -void LedgerEntrySet::entryDelete(const SLE::pointer& sle, bool unfunded) +void LedgerEntrySet::entryDelete(SLE::ref sle, bool unfunded) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -230,7 +230,7 @@ Json::Value LedgerEntrySet::getJson(int) const return ret; } -SLE::pointer LedgerEntrySet::getForMod(const uint256& node, Ledger::pointer& ledger, +SLE::pointer LedgerEntrySet::getForMod(const uint256& node, Ledger::ref ledger, boost::unordered_map& newMods) { boost::unordered_map::iterator it = mEntries.find(node); @@ -259,7 +259,7 @@ SLE::pointer LedgerEntrySet::getForMod(const uint256& node, Ledger::pointer& led } -bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, const NewcoinAddress& threadTo, Ledger::pointer& ledger, +bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, const NewcoinAddress& threadTo, Ledger::ref ledger, boost::unordered_map& newMods) { SLE::pointer sle = getForMod(Ledger::getAccountRootIndex(threadTo.getAccountID()), ledger, newMods); @@ -268,7 +268,7 @@ bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, const NewcoinAddres return threadTx(metaNode, sle, ledger, newMods); } -bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, SLE::pointer& threadTo, Ledger::pointer& ledger, +bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, SLE::ref threadTo, Ledger::ref ledger, boost::unordered_map& newMods) { // node = the node that was modified/deleted/created // threadTo = the node that needs to know @@ -282,7 +282,7 @@ bool LedgerEntrySet::threadTx(TransactionMetaNode& metaNode, SLE::pointer& threa return false; } -bool LedgerEntrySet::threadOwners(TransactionMetaNode& metaNode, SLE::pointer& node, Ledger::pointer& ledger, +bool LedgerEntrySet::threadOwners(TransactionMetaNode& metaNode, SLE::ref node, Ledger::ref ledger, boost::unordered_map& newMods) { // thread new or modified node to owner or owners if (node->hasOneOwner()) // thread to owner's account @@ -295,7 +295,7 @@ bool LedgerEntrySet::threadOwners(TransactionMetaNode& metaNode, SLE::pointer& n return false; } -void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::pointer& origLedger) +void LedgerEntrySet::calcRawMeta(Serializer& s, Ledger::ref origLedger) { // calculate the raw meta data and return it. This must be called before the set is committed // Entries modified only as a result of building the transaction metadata diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index da66cda2d2..0ab19896b9 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -24,7 +24,7 @@ public: LedgerEntryAction mAction; int mSeq; - LedgerEntrySetEntry(const SLE::pointer& e, LedgerEntryAction a, int s) : mEntry(e), mAction(a), mSeq(s) { ; } + LedgerEntrySetEntry(SLE::ref e, LedgerEntryAction a, int s) : mEntry(e), mAction(a), mSeq(s) { ; } }; @@ -38,16 +38,16 @@ protected: LedgerEntrySet(const boost::unordered_map &e, const TransactionMetaSet& s, int m) : mEntries(e), mSet(s), mSeq(m) { ; } - SLE::pointer getForMod(const uint256& node, Ledger::pointer& ledger, + SLE::pointer getForMod(const uint256& node, Ledger::ref ledger, boost::unordered_map& newMods); - bool threadTx(TransactionMetaNode& metaNode, const NewcoinAddress& threadTo, Ledger::pointer& ledger, + bool threadTx(TransactionMetaNode& metaNode, const NewcoinAddress& threadTo, Ledger::ref ledger, boost::unordered_map& newMods); - bool threadTx(TransactionMetaNode& metaNode, SLE::pointer& threadTo, Ledger::pointer& ledger, + bool threadTx(TransactionMetaNode& metaNode, SLE::ref threadTo, Ledger::ref ledger, boost::unordered_map& newMods); - bool threadOwners(TransactionMetaNode& metaNode, SLE::pointer& node, Ledger::pointer& ledger, + bool threadOwners(TransactionMetaNode& metaNode, SLE::ref node, Ledger::ref ledger, boost::unordered_map& newMods); public: @@ -66,13 +66,13 @@ public: // basic entry functions SLE::pointer getEntry(const uint256& index, LedgerEntryAction&); LedgerEntryAction hasEntry(const uint256& index) const; - void entryCache(const SLE::pointer&); // Add this entry to the cache - void entryCreate(const SLE::pointer&); // This entry will be created - void entryDelete(const SLE::pointer&, bool unfunded); - void entryModify(const SLE::pointer&); // This entry will be modified + void entryCache(SLE::ref); // Add this entry to the cache + void entryCreate(SLE::ref); // This entry will be created + void entryDelete(SLE::ref, bool unfunded); + void entryModify(SLE::ref); // This entry will be modified Json::Value getJson(int) const; - void calcRawMeta(Serializer&, Ledger::pointer& originalLedger); + void calcRawMeta(Serializer&, Ledger::ref originalLedger); // iterator functions bool isEmpty() const { return mEntries.empty(); } diff --git a/src/LedgerMaster.cpp b/src/LedgerMaster.cpp index 7228ff6b96..a3cc5a1475 100644 --- a/src/LedgerMaster.cpp +++ b/src/LedgerMaster.cpp @@ -19,23 +19,23 @@ bool LedgerMaster::addHeldTransaction(const Transaction::pointer& transaction) return mHeldTransactionsByID.insert(std::make_pair(transaction->getID(), transaction)).second; } -void LedgerMaster::pushLedger(const Ledger::pointer& newLedger) +void LedgerMaster::pushLedger(Ledger::ref newLedger) { // Caller should already have properly assembled this ledger into "ready-to-close" form -- // all candidate transactions must already be appled - Log(lsINFO) << "PushLedger: " << newLedger->getHash().GetHex(); + Log(lsINFO) << "PushLedger: " << newLedger->getHash(); ScopedLock sl(mLock); if (!!mFinalizedLedger) { mFinalizedLedger->setClosed(); - Log(lsTRACE) << "Finalizes: " << mFinalizedLedger->getHash().GetHex(); + Log(lsTRACE) << "Finalizes: " << mFinalizedLedger->getHash(); } mFinalizedLedger = mCurrentLedger; mCurrentLedger = newLedger; mEngine.setLedger(newLedger); } -void LedgerMaster::pushLedger(const Ledger::pointer& newLCL, const Ledger::pointer& newOL) +void LedgerMaster::pushLedger(Ledger::ref newLCL, Ledger::ref newOL) { assert(newLCL->isClosed() && newLCL->isAccepted()); assert(!newOL->isClosed() && !newOL->isAccepted()); @@ -45,7 +45,7 @@ void LedgerMaster::pushLedger(const Ledger::pointer& newLCL, const Ledger::point assert(newLCL->isClosed()); assert(newLCL->isImmutable()); mLedgerHistory.addAcceptedLedger(newLCL); - Log(lsINFO) << "StashAccepted: " << newLCL->getHash().GetHex(); + Log(lsINFO) << "StashAccepted: " << newLCL->getHash(); } mFinalizedLedger = newLCL; @@ -54,7 +54,7 @@ void LedgerMaster::pushLedger(const Ledger::pointer& newLCL, const Ledger::point mEngine.setLedger(newOL); } -void LedgerMaster::switchLedgers(const Ledger::pointer& lastClosed, const Ledger::pointer& current) +void LedgerMaster::switchLedgers(Ledger::ref lastClosed, Ledger::ref current) { assert(lastClosed && current); mFinalizedLedger = lastClosed; @@ -66,7 +66,7 @@ void LedgerMaster::switchLedgers(const Ledger::pointer& lastClosed, const Ledger mEngine.setLedger(mCurrentLedger); } -void LedgerMaster::storeLedger(const Ledger::pointer& ledger) +void LedgerMaster::storeLedger(Ledger::ref ledger) { mLedgerHistory.addLedger(ledger); } diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index f3e58d5ba6..8db6f34490 100644 --- a/src/LedgerMaster.h +++ b/src/LedgerMaster.h @@ -48,11 +48,11 @@ public: TER doTransaction(const SerializedTransaction& txn, uint32 targetLedger, TransactionEngineParams params); - void pushLedger(const Ledger::pointer& newLedger); - void pushLedger(const Ledger::pointer& newLCL, const Ledger::pointer& newOL); - void storeLedger(const Ledger::pointer&); + void pushLedger(Ledger::ref newLedger); + void pushLedger(Ledger::ref newLCL, Ledger::ref newOL); + void storeLedger(Ledger::ref); - void switchLedgers(const Ledger::pointer& lastClosed, const Ledger::pointer& newCurrent); + void switchLedgers(Ledger::ref lastClosed, Ledger::ref newCurrent); Ledger::pointer closeLedger(); diff --git a/src/LedgerProposal.cpp b/src/LedgerProposal.cpp index 70d9458f6c..d96b397434 100644 --- a/src/LedgerProposal.cpp +++ b/src/LedgerProposal.cpp @@ -9,14 +9,14 @@ LedgerProposal::LedgerProposal(const uint256& pLgr, uint32 seq, const uint256& tx, uint32 closeTime, const NewcoinAddress& naPeerPublic) : - mPreviousLedger(pLgr), mCurrentHash(tx), mCloseTime(closeTime), mProposeSeq(seq) + mPreviousLedger(pLgr), mCurrentHash(tx), mCloseTime(closeTime), mProposeSeq(seq), mPublicKey(naPeerPublic) { - mPublicKey = naPeerPublic; // XXX Validate key. // if (!mKey->SetPubKey(pubKey)) // throw std::runtime_error("Invalid public key in proposal"); mPeerID = mPublicKey.getNodeID(); + mTime = boost::posix_time::second_clock::universal_time(); } @@ -27,12 +27,13 @@ LedgerProposal::LedgerProposal(const NewcoinAddress& naSeed, const uint256& prev mPublicKey = NewcoinAddress::createNodePublic(naSeed); mPrivateKey = NewcoinAddress::createNodePrivate(naSeed); mPeerID = mPublicKey.getNodeID(); + mTime = boost::posix_time::second_clock::universal_time(); } LedgerProposal::LedgerProposal(const uint256& prevLgr, const uint256& position, uint32 closeTime) : mPreviousLedger(prevLgr), mCurrentHash(position), mCloseTime(closeTime), mProposeSeq(0) { - ; + mTime = boost::posix_time::second_clock::universal_time(); } uint256 LedgerProposal::getSigningHash() const @@ -55,8 +56,9 @@ bool LedgerProposal::checkSign(const std::string& signature, const uint256& sign void LedgerProposal::changePosition(const uint256& newPosition, uint32 closeTime) { - mCurrentHash = newPosition; - mCloseTime = closeTime; + mCurrentHash = newPosition; + mCloseTime = closeTime; + mTime = boost::posix_time::second_clock::universal_time(); ++mProposeSeq; } diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h index 70d4bbbe7a..c9c6fa8dd9 100644 --- a/src/LedgerProposal.h +++ b/src/LedgerProposal.h @@ -22,7 +22,8 @@ protected: NewcoinAddress mPublicKey; NewcoinAddress mPrivateKey; // If ours - std::string mSignature; // set only if needed + std::string mSignature; // set only if needed + boost::posix_time::ptime mTime; public: @@ -55,7 +56,11 @@ public: void setPrevLedger(const uint256& prevLedger) { mPreviousLedger = prevLedger; } void setSignature(const std::string& signature) { mSignature = signature; } + bool hasSignature() { return !mSignature.empty(); } + bool isPrevLedger(const uint256& pl) { return mPreviousLedger == pl; } + const boost::posix_time::ptime getCreateTime() { return mTime; } + bool isStale(boost::posix_time::ptime cutoff) { return mTime <= cutoff; } void changePosition(const uint256& newPosition, uint32 newCloseTime); Json::Value getJson() const; diff --git a/src/LedgerTiming.cpp b/src/LedgerTiming.cpp index a29f7ad2fa..b19ee994bd 100644 --- a/src/LedgerTiming.cpp +++ b/src/LedgerTiming.cpp @@ -12,7 +12,7 @@ int ContinuousLedgerTiming::LedgerTimeResolution[] = { 10, 10, 20, 30, 60, 90, 1 // Called when a ledger is open and no close is in progress -- when a transaction is received and no close // is in process, or when a close completes. Returns the number of seconds the ledger should be be open. -int ContinuousLedgerTiming::shouldClose( +bool ContinuousLedgerTiming::shouldClose( bool anyTransactions, int previousProposers, // proposers in the last closing int proposersClosed, // proposers who have currently closed this ledgers @@ -27,16 +27,16 @@ int ContinuousLedgerTiming::shouldClose( boost::str(boost::format("CLC::shouldClose range Trans=%s, Prop: %d/%d, Secs: %d (last:%d)") % (anyTransactions ? "yes" : "no") % previousProposers % proposersClosed % currentMSeconds % previousMSeconds); - return currentMSeconds; + return true;; } if (!anyTransactions) { // no transactions so far this interval if (proposersClosed > (previousProposers / 4)) // did we miss a transaction? { - Log(lsTRACE) << "no transactions, many proposers: now (" << proposersClosed << "closed, " + Log(lsTRACE) << "no transactions, many proposers: now (" << proposersClosed << " closed, " << previousProposers << " before)"; - return currentMSeconds; + return true; } #if 0 // This false triggers on the genesis ledger if (previousMSeconds > (1000 * (LEDGER_IDLE_INTERVAL + 2))) // the last ledger was very slow to close @@ -47,11 +47,10 @@ int ContinuousLedgerTiming::shouldClose( return previousMSeconds - 1000; } #endif - return idleInterval * 1000; // normal idle + return currentMSeconds >= (idleInterval * 1000); // normal idle } - Log(lsTRACE) << "close now"; - return currentMSeconds; // this ledger should close now + return true; // this ledger should close now } // Returns whether we have a consensus or not. If so, we expect all honest nodes diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index bed4673319..80e89b30f4 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -28,6 +28,12 @@ // How often we check state or change positions (in milliseconds) # define LEDGER_GRANULARITY 1000 +// How long we consider a proposal fresh +# define PROPOSE_FRESHNESS 20 + +// How often we force generating a new proposal to keep ours fresh +# define PROPOSE_INTERVAL 12 + // Avalanche tuning #define AV_INIT_CONSENSUS_PCT 50 // percentage of nodes on our UNL that must vote yes @@ -46,7 +52,7 @@ public: // Returns the number of seconds the ledger was or should be open // Call when a consensus is reached and when any transaction is relayed to be added - static int shouldClose( + static bool shouldClose( bool anyTransactions, int previousProposers, int proposersClosed, int previousSeconds, int currentSeconds, diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 06d4b64a5f..fc2b547541 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -25,7 +25,7 @@ NetworkOPs::NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedgerMaster) : mMode(omDISCONNECTED),mNetTimer(io_service), mLedgerMaster(pLedgerMaster), mCloseTimeOffset(0), - mLastCloseProposers(0), mLastCloseConvergeTime(LEDGER_IDLE_INTERVAL) + mLastCloseProposers(0), mLastCloseConvergeTime(LEDGER_IDLE_INTERVAL), mLastValidationTime(0) { } @@ -46,6 +46,22 @@ uint32 NetworkOPs::getCloseTimeNC() return iToSeconds(getNetworkTimePT() + boost::posix_time::seconds(mCloseTimeOffset)); } +uint32 NetworkOPs::getValidationTimeNC() +{ + uint32 vt = getNetworkTimeNC(); + if (vt <= mLastValidationTime) + vt = mLastValidationTime + 1; + mLastValidationTime = vt; + return vt; +} + +void NetworkOPs::closeTimeOffset(int offset) +{ + mCloseTimeOffset += offset / 4; + if (mCloseTimeOffset) + Log(lsINFO) << "Close time offset now " << mCloseTimeOffset; +} + uint32 NetworkOPs::getCurrentLedgerID() { return mLedgerMaster->getCurrentLedger()->getLedgerSeq(); @@ -429,8 +445,9 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis { boost::unordered_map current = theApp->getValidations().getCurrentValidations(); - for (boost::unordered_map::iterator it = current.begin(), end = current.end(); it != end; ++it) - ledgers[it->first].trustedValidations += it->second; + typedef std::pair u256_int_pair; + BOOST_FOREACH(u256_int_pair& it, current) + ledgers[it.first].trustedValidations += it.second; } Ledger::pointer ourClosed = mLedgerMaster->getClosedLedger(); @@ -444,7 +461,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis ourVC.highNode = theApp->getWallet().getNodePublic(); } - BOOST_FOREACH(const Peer::pointer& it, peerList) + BOOST_FOREACH(Peer::ref it, peerList) { if (!it) { @@ -460,7 +477,6 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis vc.highNode = it->getNodePublic(); ++vc.nodesUsing; } - else Log(lsTRACE) << "Connected peer announces no LCL " << it->getIP(); } } @@ -472,7 +488,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis it != end; ++it) { bool isDead = theApp->getValidations().isDeadLedger(it->first); - Log(lsTRACE) << "L: " << it->first.GetHex() << ((isDead) ? " dead" : " live") << + Log(lsTRACE) << "L: " << it->first << ((isDead) ? " dead" : " live") << " t=" << it->second.trustedValidations << ", n=" << it->second.nodesUsing; if ((it->second > bestVC) && !isDead) { @@ -502,16 +518,17 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis } Log(lsWARNING) << "We are not running on the consensus ledger"; - Log(lsINFO) << "Our LCL " << ourClosed->getHash().GetHex(); - Log(lsINFO) << "Net LCL " << closedLedger.GetHex(); + Log(lsINFO) << "Our LCL " << ourClosed->getHash(); + Log(lsINFO) << "Net LCL " << closedLedger; if ((mMode == omTRACKING) || (mMode == omFULL)) setMode(omCONNECTED); Ledger::pointer consensus = mLedgerMaster->getLedgerByHash(closedLedger); if (!consensus) { - Log(lsINFO) << "Acquiring consensus ledger " << closedLedger.GetHex(); - LedgerAcquire::pointer mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(closedLedger); + Log(lsINFO) << "Acquiring consensus ledger " << closedLedger; + if (!mAcquiringLedger || (mAcquiringLedger->getHash() != closedLedger)) + mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(closedLedger); if (!mAcquiringLedger || mAcquiringLedger->isFailed()) { theApp->getMasterLedgerAcquire().dropLedger(closedLedger); @@ -522,7 +539,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis { // add more peers int count = 0; std::vector peers=theApp->getConnectionPool().getPeerVector(); - BOOST_FOREACH(const Peer::pointer& it, peerList) + BOOST_FOREACH(Peer::ref it, peerList) { if (it->getClosedLedgerHash() == closedLedger) { @@ -532,7 +549,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis } if (!count) { // just ask everyone - BOOST_FOREACH(const Peer::pointer& it, peerList) + BOOST_FOREACH(Peer::ref it, peerList) if (it->isConnected()) mAcquiringLedger->peerHas(it); } @@ -552,9 +569,9 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger, bool duringCo { // set the newledger as our last closed ledger -- this is abnormal code if (duringConsensus) - Log(lsERROR) << "JUMPdc last closed ledger to " << newLedger->getHash().GetHex(); + Log(lsERROR) << "JUMPdc last closed ledger to " << newLedger->getHash(); else - Log(lsERROR) << "JUMP last closed ledger to " << newLedger->getHash().GetHex(); + Log(lsERROR) << "JUMP last closed ledger to " << newLedger->getHash(); newLedger->setClosed(); Ledger::pointer openLedger = boost::make_shared(false, boost::ref(*newLedger)); @@ -575,7 +592,7 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger, bool duringCo int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger) { Log(lsINFO) << "Consensus time for ledger " << closingLedger->getLedgerSeq(); - Log(lsINFO) << " LCL is " << closingLedger->getParentHash().GetHex(); + Log(lsINFO) << " LCL is " << closingLedger->getParentHash(); Ledger::pointer prevLedger = mLedgerMaster->getLedgerByHash(closingLedger->getParentHash()); if (!prevLedger) @@ -598,8 +615,8 @@ int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer clo } // <-- bool: true to relay -bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint32 closeTime, - const std::string& pubKey, const std::string& signature, const NewcoinAddress& nodePublic) +bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger, + uint32 closeTime, const std::string& pubKey, const std::string& signature, const NewcoinAddress& nodePublic) { // JED: does mConsensus need to be locked? @@ -607,10 +624,13 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint // XXX Take a vuc for pubkey. // Get a preliminary hash to use to suppress duplicates - Serializer s(128); + Serializer s(256); + s.add256(proposeHash); + s.add256(prevLedger); s.add32(proposeSeq); - s.add32(getCurrentLedgerID()); + s.add32(closeTime); s.addRaw(pubKey); + s.addRaw(signature); if (!theApp->isNew(s.getSHA512Half())) return false; @@ -630,7 +650,29 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint if (!mConsensus) { Log(lsINFO) << "Received proposal outside consensus window"; - return (mMode != omFULL); + return mMode != omFULL; + } + + // Is this node on our UNL? + if (!theApp->getUNL().nodeInUNL(naPeerPublic)) + { + Log(lsINFO) << "Untrusted proposal: " << naPeerPublic.humanNodePublic() << " " << proposeHash; + return true; + } + + if (prevLedger.isNonZero()) + { // new-style + LedgerProposal::pointer proposal = + boost::make_shared(prevLedger, proposeSeq, proposeHash, closeTime, naPeerPublic); + if (!proposal->checkSign(signature)) + { + Log(lsWARNING) << "New-style ledger proposal fails signature check"; + return false; + } + if (prevLedger == mConsensus->getLCL()) + return mConsensus->peerPosition(proposal); + mConsensus->deferProposal(proposal, nodePublic); + return false; } LedgerProposal::pointer proposal = @@ -638,22 +680,10 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint if (!proposal->checkSign(signature)) { // Note that if the LCL is different, the signature check will fail Log(lsWARNING) << "Ledger proposal fails signature check"; - if ((mMode != omFULL) && (mMode != omTRACKING) && theApp->getUNL().nodeInUNL(proposal->peekPublic())) - { - proposal->setSignature(signature); - mConsensus->deferProposal(proposal, nodePublic); - } + proposal->setSignature(signature); + mConsensus->deferProposal(proposal, nodePublic); return false; } - - // Is this node on our UNL? - if (!theApp->getUNL().nodeInUNL(proposal->peekPublic())) - { - Log(lsINFO) << "Untrusted proposal: " << naPeerPublic.humanNodePublic() << " " << - proposal->getCurrentHash().GetHex(); - return true; - } - return mConsensus->peerPosition(proposal); } @@ -688,10 +718,10 @@ void NetworkOPs::mapComplete(const uint256& hash, const SHAMap::pointer& map) void NetworkOPs::endConsensus(bool correctLCL) { uint256 deadLedger = theApp->getMasterLedger().getClosedLedger()->getParentHash(); - Log(lsTRACE) << "Ledger " << deadLedger.GetHex() << " is now dead"; + Log(lsTRACE) << "Ledger " << deadLedger << " is now dead"; theApp->getValidations().addDeadLedger(deadLedger); std::vector peerList = theApp->getConnectionPool().getPeerVector(); - BOOST_FOREACH(const Peer::pointer& it, peerList) + BOOST_FOREACH(Peer::ref it, peerList) if (it && (it->getClosedLedgerHash() == deadLedger)) { Log(lsTRACE) << "Killing obsolete peer status"; @@ -768,7 +798,7 @@ std::vector bool NetworkOPs::recvValidation(const SerializedValidation::pointer& val) { - Log(lsINFO) << "recvValidation " << val->getLedgerHash().GetHex(); + Log(lsINFO) << "recvValidation " << val->getLedgerHash(); return theApp->getValidations().addValidation(val); } @@ -798,7 +828,7 @@ Json::Value NetworkOPs::getServerInfo() // Monitoring: publisher side // -Json::Value NetworkOPs::pubBootstrapAccountInfo(const Ledger::pointer& lpAccepted, const NewcoinAddress& naAccountID) +Json::Value NetworkOPs::pubBootstrapAccountInfo(Ledger::ref lpAccepted, const NewcoinAddress& naAccountID) { Json::Value jvObj(Json::objectValue); @@ -833,7 +863,7 @@ void NetworkOPs::pubAccountInfo(const NewcoinAddress& naAccountID, const Json::V } } -void NetworkOPs::pubLedger(const Ledger::pointer& lpAccepted) +void NetworkOPs::pubLedger(Ledger::ref lpAccepted) { { boost::interprocess::sharable_lock sl(mMonitorLock); @@ -946,7 +976,7 @@ Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TER terRes return jvObj; } -void NetworkOPs::pubTransactionAll(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState) +void NetworkOPs::pubTransactionAll(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState) { Json::Value jvObj = transJson(stTxn, terResult, pState, lpCurrent->getLedgerSeq(), "transaction"); @@ -956,7 +986,7 @@ void NetworkOPs::pubTransactionAll(const Ledger::pointer& lpCurrent, const Seria } } -void NetworkOPs::pubTransactionAccounts(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState) +void NetworkOPs::pubTransactionAccounts(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState) { boost::unordered_set usisNotify; @@ -991,7 +1021,7 @@ void NetworkOPs::pubTransactionAccounts(const Ledger::pointer& lpCurrent, const } } -void NetworkOPs::pubTransaction(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult) +void NetworkOPs::pubTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult) { boost::interprocess::sharable_lock sl(mMonitorLock); diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 5e53b98194..25ac145f40 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -64,6 +64,7 @@ protected: int mLastCloseProposers, mLastCloseConvergeTime; uint256 mLastCloseHash; uint32 mLastCloseTime; + uint32 mLastValidationTime; // XXX Split into more locks. boost::interprocess::interprocess_upgradable_mutex mMonitorLock; @@ -78,10 +79,10 @@ protected: void setMode(OperatingMode); Json::Value transJson(const SerializedTransaction& stTxn, TER terResult, const std::string& strStatus, int iSeq, const std::string& strType); - void pubTransactionAll(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState); - void pubTransactionAccounts(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState); + void pubTransactionAll(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState); + void pubTransactionAccounts(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState); - Json::Value pubBootstrapAccountInfo(const Ledger::pointer& lpAccepted, const NewcoinAddress& naAccountID); + Json::Value pubBootstrapAccountInfo(Ledger::ref lpAccepted, const NewcoinAddress& naAccountID); public: NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedgerMaster); @@ -89,6 +90,8 @@ public: // network information uint32 getNetworkTimeNC(); uint32 getCloseTimeNC(); + uint32 getValidationTimeNC(); + void closeTimeOffset(int); boost::posix_time::ptime getNetworkTimePT(); uint32 getCurrentLedgerID(); OperatingMode getOperatingMode() { return mMode; } @@ -159,7 +162,7 @@ public: const std::vector& myNode, std::list< std::vector >& newNodes); // ledger proposal/close functions - bool recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint32 closeTime, + bool recvPropose(uint32 proposeSeq, const uint256& proposeHash, const uint256& prevLedger, uint32 closeTime, const std::string& pubKey, const std::string& signature, const NewcoinAddress& nodePublic); bool gotTXData(const boost::shared_ptr& peer, const uint256& hash, const std::list& nodeIDs, const std::list< std::vector >& nodeData); @@ -195,8 +198,8 @@ public: // void pubAccountInfo(const NewcoinAddress& naAccountID, const Json::Value& jvObj); - void pubLedger(const Ledger::pointer& lpAccepted); - void pubTransaction(const Ledger::pointer& lpLedger, const SerializedTransaction& stTxn, TER terResult); + void pubLedger(Ledger::ref lpAccepted); + void pubTransaction(Ledger::ref lpLedger, const SerializedTransaction& stTxn, TER terResult); // // Monitoring: subscriber side diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 29b87fe378..be7583dcd7 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -95,6 +95,15 @@ NewcoinAddress NewcoinAddress::createNodePublic(const std::vector return naNew; } +NewcoinAddress NewcoinAddress::createNodePublic(const std::string& strPublic) +{ + NewcoinAddress naNew; + + naNew.setNodePublic(strPublic); + + return naNew; +} + uint160 NewcoinAddress::getNodeID() const { switch (nVersion) { diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index c591d1b0d7..369b609d04 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -46,6 +46,7 @@ public: static NewcoinAddress createNodePublic(const NewcoinAddress& naSeed); static NewcoinAddress createNodePublic(const std::vector& vPublic); + static NewcoinAddress createNodePublic(const std::string& strPublic); // // Node Private diff --git a/src/Peer.cpp b/src/Peer.cpp index 1ca2d8fa58..27db8ff017 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -140,7 +140,7 @@ void Peer::handleVerifyTimer(const boost::system::error_code& ecResult) // Begin trying to connect. We are not connected till we know and accept peer's public key. // Only takes IP addresses (not domains). -void Peer::connect(const std::string strIp, int iPort) +void Peer::connect(const std::string& strIp, int iPort) { int iPortAct = (iPort <= 0) ? SYSTEM_PEER_PORT : iPort; @@ -586,7 +586,10 @@ void Peer::recvHello(newcoin::TMHello& packet) if (packet.has_nettime() && ((packet.nettime() < minTime) || (packet.nettime() > maxTime))) { - Log(lsINFO) << "Recv(Hello): Disconnect: Clock is far off"; + if (packet.nettime() > maxTime) + Log(lsINFO) << "Recv(Hello): " << getIP() << " :Clock far off +" << packet.nettime() - ourTime; + else if(packet.nettime() < minTime) + Log(lsINFO) << "Recv(Hello): " << getIP() << " :Clock far off -" << ourTime - packet.nettime(); } else if (packet.protoversionmin() < MAKE_VERSION_INT(MIN_PROTO_MAJOR, MIN_PROTO_MINOR)) { @@ -721,11 +724,13 @@ void Peer::recvPropose(newcoin::TMProposeSet& packet) return; } - uint32 proposeSeq = packet.proposeseq(); - uint256 currentTxHash; + uint256 currentTxHash, prevLedger; memcpy(currentTxHash.begin(), packet.currenttxhash().data(), 32); - if(theApp->getOPs().recvPropose(proposeSeq, currentTxHash, packet.closetime(), + if ((packet.has_previousledger()) && (packet.previousledger().size() == 32)) + memcpy(prevLedger.begin(), packet.previousledger().data(), 32); + + if(theApp->getOPs().recvPropose(packet.proposeseq(), currentTxHash, prevLedger, packet.closetime(), packet.nodepubkey(), packet.signature(), mNodePublic)) { // FIXME: Not all nodes will want proposals PackedMessage::pointer message = boost::make_shared(packet, newcoin::mtPROPOSE_LEDGER); @@ -899,15 +904,18 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet) if (packet.newevent() == newcoin::neLOST_SYNC) { - Log(lsTRACE) << "peer has lost sync " << getIP(); + if (!mClosedLedgerHash.isZero()) + { + Log(lsTRACE) << "peer has lost sync " << getIP(); + mClosedLedgerHash.zero(); + } mPreviousLedgerHash.zero(); - mClosedLedgerHash.zero(); return; } if (packet.has_ledgerhash() && (packet.ledgerhash().size() == (256 / 8))) { // a peer has changed ledgers memcpy(mClosedLedgerHash.begin(), packet.ledgerhash().data(), 256 / 8); - Log(lsTRACE) << "peer LCL is " << mClosedLedgerHash.GetHex() << " " << getIP(); + Log(lsTRACE) << "peer LCL is " << mClosedLedgerHash << " " << getIP(); } else { @@ -967,6 +975,8 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) } memcpy(ledgerhash.begin(), packet.ledgerhash().data(), 32); ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash); + if (!ledger) + Log(lsINFO) << "Don't have ledger " << ledgerhash; } else if (packet.has_ledgerseq()) ledger = theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq()); @@ -985,7 +995,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) return; } - if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq()!=ledger->getLedgerSeq()))) + if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq() != ledger->getLedgerSeq()))) { punishPeer(PP_UNKNOWN_REQUEST); Log(lsWARNING) << "Can't find the ledger they want"; diff --git a/src/Peer.h b/src/Peer.h index 85666c9c69..13c5fdb2de 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -24,13 +24,14 @@ typedef std::pair ipPort; class Peer : public boost::enable_shared_from_this { public: - typedef boost::shared_ptr pointer; + typedef boost::shared_ptr pointer; + typedef const boost::shared_ptr& ref; static const int psbGotHello = 0, psbSentHello = 1, psbInMap = 2, psbTrusted = 3; static const int psbNoLedgers = 4, psbNoTransactions = 5, psbDownLevel = 6; void handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it); - static void sHandleConnect(const Peer::pointer& ptr, const boost::system::error_code& error, + static void sHandleConnect(Peer::ref ptr, const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it) { ptr->handleConnect(error, it); } @@ -50,11 +51,11 @@ private: boost::asio::deadline_timer mVerifyTimer; void handleStart(const boost::system::error_code& ecResult); - static void sHandleStart(const Peer::pointer& ptr, const boost::system::error_code& ecResult) + static void sHandleStart(Peer::ref ptr, const boost::system::error_code& ecResult) { ptr->handleStart(ecResult); } void handleVerifyTimer(const boost::system::error_code& ecResult); - static void sHandleVerifyTimer(const Peer::pointer& ptr, const boost::system::error_code& ecResult) + static void sHandleVerifyTimer(Peer::ref ptr, const boost::system::error_code& ecResult) { ptr->handleVerifyTimer(ecResult); } protected: @@ -68,19 +69,19 @@ protected: Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx); void handleShutdown(const boost::system::error_code& error) { ; } - static void sHandleShutdown(const Peer::pointer& ptr, const boost::system::error_code& error) + static void sHandleShutdown(Peer::ref ptr, const boost::system::error_code& error) { ptr->handleShutdown(error); } void handle_write(const boost::system::error_code& error, size_t bytes_transferred); - static void sHandle_write(const Peer::pointer& ptr, const boost::system::error_code& error, size_t bytes_transferred) + static void sHandle_write(Peer::ref ptr, const boost::system::error_code& error, size_t bytes_transferred) { ptr->handle_write(error, bytes_transferred); } void handle_read_header(const boost::system::error_code& error); - static void sHandle_read_header(const Peer::pointer& ptr, const boost::system::error_code& error) + static void sHandle_read_header(Peer::ref ptr, const boost::system::error_code& error) { ptr->handle_read_header(error); } void handle_read_body(const boost::system::error_code& error); - static void sHandle_read_body(const Peer::pointer& ptr, const boost::system::error_code& error) + static void sHandle_read_body(Peer::ref ptr, const boost::system::error_code& error) { ptr->handle_read_body(error); } void processReadBuffer(); @@ -134,26 +135,26 @@ public: return mSocketSsl.lowest_layer(); } - void connect(const std::string strIp, int iPort); + void connect(const std::string& strIp, int iPort); void connected(const boost::system::error_code& error); void detach(const char *); - bool samePeer(const Peer::pointer& p) { return samePeer(*p); } - bool samePeer(const Peer& p) { return this == &p; } + bool samePeer(Peer::ref p) { return samePeer(*p); } + bool samePeer(const Peer& p) { return this == &p; } void sendPacket(const PackedMessage::pointer& packet); - void sendLedgerProposal(const Ledger::pointer& ledger); - void sendFullLedger(const Ledger::pointer& ledger); + void sendLedgerProposal(Ledger::ref ledger); + void sendFullLedger(Ledger::ref ledger); void sendGetFullLedger(uint256& hash); void sendGetPeers(); void punishPeer(PeerPunish pp); Json::Value getJson(); - bool isConnected() const { return mHelloed && !mDetaching; } + bool isConnected() const { return mHelloed && !mDetaching; } - uint256 getClosedLedgerHash() const { return mClosedLedgerHash; } + uint256 getClosedLedgerHash() const { return mClosedLedgerHash; } bool hasLedger(const uint256& hash) const; - NewcoinAddress getNodePublic() const { return mNodePublic; } + NewcoinAddress getNodePublic() const { return mNodePublic; } void cycleStatus() { mPreviousLedgerHash = mClosedLedgerHash; mClosedLedgerHash.zero(); } }; diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp index 2a9b48520b..8ae69c405e 100644 --- a/src/SHAMap.cpp +++ b/src/SHAMap.cpp @@ -125,7 +125,7 @@ void SHAMap::dirtyUp(std::stack& stack, const uint256& return; } #ifdef ST_DEBUG - std::cerr << "dirtyUp sets branch " << branch << " to " << prevHash.GetHex() << std::endl; + std::cerr << "dirtyUp sets branch " << branch << " to " << prevHash << std::endl; #endif prevHash = node->getNodeHash(); assert(prevHash.isNonZero()); @@ -187,9 +187,9 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has if (node->getNodeHash() != hash) { std::cerr << "Attempt to get node, hash not in tree" << std::endl; - std::cerr << "ID: " << id.getString() << std::endl; - std::cerr << "TgtHash " << hash.GetHex() << std::endl; - std::cerr << "NodHash " << node->getNodeHash().GetHex() << std::endl; + std::cerr << "ID: " << id << std::endl; + std::cerr << "TgtHash " << hash << std::endl; + std::cerr << "NodHash " << node->getNodeHash() << std::endl; dump(); throw std::runtime_error("invalid node"); } @@ -242,7 +242,7 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node) { // Return the first item below this node #ifdef ST_DEBUG - std::cerr << "firstBelow(" << node->getString() << ")" << std::endl; + std::cerr << "firstBelow(" << *node << ")" << std::endl; #endif do { // Walk down the tree @@ -253,9 +253,9 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node) if (!node->isEmptyBranch(i)) { #ifdef ST_DEBUG - std::cerr << " FB: node " << node->getString() << std::endl; + std::cerr << " FB: node " << *node << std::endl; std::cerr << " has non-empty branch " << i << " : " << - node->getChildNodeID(i).getString() << ", " << node->getChildHash(i).GetHex() << std::endl; + node->getChildNodeID(i) << ", " << node->getChildHash(i) << std::endl; #endif node = getNodePointer(node->getChildNodeID(i), node->getChildHash(i)); foundNode = true; @@ -268,7 +268,7 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node) SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode* node) { #ifdef DEBUG - std::cerr << "lastBelow(" << node->getString() << ")" << std::endl; + std::cerr << "lastBelow(" << *node << ")" << std::endl; #endif do @@ -306,7 +306,7 @@ SHAMapItem::pointer SHAMap::onlyBelow(SHAMapTreeNode* node) if (!found) { - std::cerr << node->getString() << std::endl; + std::cerr << *node << std::endl; assert(false); return SHAMapItem::pointer(); } @@ -480,7 +480,7 @@ bool SHAMap::delItem(const uint256& id) { eraseChildren(node); #ifdef ST_DEBUG - std::cerr << "Making item node " << node->getString() << std::endl; + std::cerr << "Making item node " << *node << std::endl; #endif node->setItem(item, type); } @@ -501,7 +501,7 @@ bool SHAMap::delItem(const uint256& id) bool SHAMap::addGiveItem(const SHAMapItem::pointer& item, bool isTransaction, bool hasMeta) { // add the specified item, does not update #ifdef ST_DEBUG - std::cerr << "aGI " << item->getTag().GetHex() << std::endl; + std::cerr << "aGI " << item->getTag() << std::endl; #endif uint256 tag = item->getTag(); @@ -527,7 +527,7 @@ bool SHAMap::addGiveItem(const SHAMapItem::pointer& item, bool isTransaction, bo if (node->isInner()) { // easy case, we end on an inner node #ifdef ST_DEBUG - std::cerr << "aGI inner " << node->getString() << std::endl; + std::cerr << "aGI inner " << *node << std::endl; #endif int branch = node->selectBranch(tag); assert(node->isEmptyBranch(branch)); @@ -535,8 +535,8 @@ bool SHAMap::addGiveItem(const SHAMapItem::pointer& item, bool isTransaction, bo boost::make_shared(node->getChildNodeID(branch), item, type, mSeq); if (!mTNByID.insert(std::make_pair(SHAMapNode(*newNode), newNode)).second) { - std::cerr << "Node: " << node->getString() << std::endl; - std::cerr << "NewNode: " << newNode->getString() << std::endl; + std::cerr << "Node: " << *node << std::endl; + std::cerr << "NewNode: " << *newNode << std::endl; dump(); assert(false); throw std::runtime_error("invalid inner node"); @@ -546,8 +546,8 @@ bool SHAMap::addGiveItem(const SHAMapItem::pointer& item, bool isTransaction, bo else { // this is a leaf node that has to be made an inner node holding two items #ifdef ST_DEBUG - std::cerr << "aGI leaf " << node->getString() << std::endl; - std::cerr << "Existing: " << node->peekItem()->getTag().GetHex() << std::endl; + std::cerr << "aGI leaf " << *node << std::endl; + std::cerr << "Existing: " << node->peekItem()->getTag() << std::endl; #endif SHAMapItem::pointer otherItem = node->peekItem(); assert(otherItem && (tag != otherItem->getTag())); @@ -629,7 +629,7 @@ bool SHAMap::updateGiveItem(const SHAMapItem::pointer& item, bool isTransaction, void SHAMapItem::dump() { - std::cerr << "SHAMapItem(" << mTag.GetHex() << ") " << mData.size() << "bytes" << std::endl; + std::cerr << "SHAMapItem(" << mTag << ") " << mData.size() << "bytes" << std::endl; } SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const uint256& hash) @@ -652,7 +652,7 @@ SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const ui } catch (...) { - Log(lsWARNING) << "fetchNodeExternal gets an invalid node: " << hash.GetHex(); + Log(lsWARNING) << "fetchNodeExternal gets an invalid node: " << hash; throw SHAMapMissingNode(id, hash); } } @@ -719,7 +719,7 @@ void SHAMap::dump(bool hash) SHAMapItem::pointer i=peekFirstItem(); while (i) { - std::cerr << "Item: id=" << i->getTag().GetHex() << std::endl; + std::cerr << "Item: id=" << i->getTag() << std::endl; i = peekNextItem(i->getTag()); } std::cerr << "SHAMap::dump done" << std::endl; @@ -732,7 +732,7 @@ void SHAMap::dump(bool hash) { std::cerr << it->second->getString() << std::endl; if (hash) - std::cerr << " " << it->second->getNodeHash().GetHex() << std::endl; + std::cerr << " " << it->second->getNodeHash() << std::endl; } } diff --git a/src/SHAMap.h b/src/SHAMap.h index 2e5c0ccbc8..b84dcb7272 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -78,6 +78,8 @@ public: extern std::size_t hash_value(const SHAMapNode& mn); +inline std::ostream& operator<<(std::ostream& out, const SHAMapNode& node) { return out << node.getString(); } + class SHAMapItem { // an item stored in a SHAMap public: diff --git a/src/SHAMapNodes.cpp b/src/SHAMapNodes.cpp index 144ccaf993..65514ad95f 100644 --- a/src/SHAMapNodes.cpp +++ b/src/SHAMapNodes.cpp @@ -73,7 +73,7 @@ bool SHAMapNode::operator!=(const uint256 &s) const return s != mNodeID; } -static bool j = SHAMapNode::ClassInit(); +bool SMN_j = SHAMapNode::ClassInit(); bool SHAMapNode::ClassInit() { // set up the depth masks @@ -147,7 +147,7 @@ int SHAMapNode::selectBranch(const uint256& hash) const if ((hash & smMasks[mDepth]) != mNodeID) { std::cerr << "selectBranch(" << getString() << std::endl; - std::cerr << " " << hash.GetHex() << " off branch" << std::endl; + std::cerr << " " << hash << " off branch" << std::endl; assert(false); return -1; // does not go under this node } @@ -464,7 +464,7 @@ void SHAMapTreeNode::makeInner() void SHAMapTreeNode::dump() { - Log(lsDEBUG) << "SHAMapTreeNode(" << getNodeID().GetHex() << ")"; + Log(lsDEBUG) << "SHAMapTreeNode(" << getNodeID() << ")"; } std::string SHAMapTreeNode::getString() const diff --git a/src/SHAMapSync.cpp b/src/SHAMapSync.cpp index ee3bb0e1d5..5ae0af44c5 100644 --- a/src/SHAMapSync.cpp +++ b/src/SHAMapSync.cpp @@ -66,7 +66,7 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vectorgetString(); + Log(lsTRACE) << "Got sync node from cache: " << *d; mTNByID[*d] = d; } } @@ -222,8 +222,8 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vectorgetDepth() != (node.getDepth() - 1)) { // Either this node is broken or we didn't request it (yet) - Log(lsINFO) << "unable to hook node " << node.getString(); - Log(lsINFO) << " stuck at " << iNode->getString(); + Log(lsINFO) << "unable to hook node " << node; + Log(lsINFO) << " stuck at " << *iNode; Log(lsINFO) << "got depth=" << node.getDepth() << ", walked to= " << iNode->getDepth(); return false; } @@ -304,7 +304,7 @@ bool SHAMap::deepCompare(SHAMap& other) return false; } -// Log(lsTRACE) << "Comparing inner nodes " << node->getString(); +// Log(lsTRACE) << "Comparing inner nodes " << *node; if (node->getNodeHash() != otherNode->getNodeHash()) return false; diff --git a/src/SNTPClient.cpp b/src/SNTPClient.cpp index d204b6a8ec..bb1daa098b 100644 --- a/src/SNTPClient.cpp +++ b/src/SNTPClient.cpp @@ -14,8 +14,8 @@ static uint8_t SNTPQueryData[48] = { 0x1B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -// NTP query frequency - 5 minutes -#define NTP_QUERY_FREQUENCY (5 * 60) +// NTP query frequency - 4 minutes +#define NTP_QUERY_FREQUENCY (4 * 60) // NTP minimum interval to query same servers - 3 minutes #define NTP_MIN_QUERY (3 * 60) @@ -26,6 +26,9 @@ static uint8_t SNTPQueryData[48] = // NTP timestamp constant #define NTP_UNIX_OFFSET 0x83AA7E80 +// NTP timestamp validity +#define NTP_TIMESTAMP_VALID ((NTP_QUERY_FREQUENCY + NTP_MIN_QUERY) * 2) + // SNTP packet offsets #define NTP_OFF_INFO 0 #define NTP_OFF_ROOTDELAY 1 @@ -215,7 +218,7 @@ void SNTPClient::queryAll() bool SNTPClient::getOffset(int& offset) { boost::mutex::scoped_lock sl(mLock); - if ((mLastOffsetUpdate == (time_t) -1) || ((mLastOffsetUpdate + 90) < time(NULL))) + if ((mLastOffsetUpdate == (time_t) -1) || ((mLastOffsetUpdate + NTP_TIMESTAMP_VALID) < time(NULL))) return false; offset = mOffset; return true; diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index 21faba8c35..1069887cc2 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -8,14 +8,15 @@ class SerializedLedgerEntry : public SerializedType { public: - typedef boost::shared_ptr pointer; + typedef boost::shared_ptr pointer; + typedef const boost::shared_ptr& ref; protected: - uint256 mIndex; - LedgerEntryType mType; - STUInt16 mVersion; - STObject mObject; - const LedgerEntryFormat* mFormat; + uint256 mIndex; + LedgerEntryType mType; + STUInt16 mVersion; + STObject mObject; + const LedgerEntryFormat* mFormat; SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); } diff --git a/src/SerializedObject.h b/src/SerializedObject.h index fde0d7ec3f..d53dd5ed12 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -92,6 +92,7 @@ enum SOE_Field sfSequence, sfSignature, sfSigningKey, + sfSigningTime, sfSourceTag, sfTakerGets, sfTakerPays, diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index b875acffb1..98461f5444 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -100,6 +100,7 @@ public: inline SerializedType* new_clone(const SerializedType& s) { return s.clone().release(); } inline void delete_clone(const SerializedType* s) { boost::checked_delete(s); } +inline std::ostream& operator<<(std::ostream& out, const SerializedType& t) { return out << t.getFullText(); } class STUInt8 : public SerializedType { diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index a87aa141e5..9ae32c31bb 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -6,7 +6,7 @@ SOElement SerializedValidation::sValidationFormat[] = { { sfFlags, "Flags", STI_UINT32, SOE_FLAGS, 0 }, { sfLedgerHash, "LedgerHash", STI_HASH256, SOE_REQUIRED, 0 }, - { sfCloseTime, "CloseTime", STI_UINT32, SOE_REQUIRED, 0 }, + { sfSigningTime, "SignTime", STI_UINT32, SOE_REQUIRED, 0 }, { sfSigningKey, "SigningKey", STI_VL, SOE_REQUIRED, 0 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 }, }; @@ -19,12 +19,12 @@ SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSi if (checkSignature && !isValid()) throw std::runtime_error("Invalid validation"); } -SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 closeTime, +SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 signTime, const NewcoinAddress& naSeed, bool isFull) : STObject(sValidationFormat), mSignature("Signature"), mTrusted(false) { setValueFieldH256(sfLedgerHash, ledgerHash); - setValueFieldU32(sfCloseTime, closeTime); + setValueFieldU32(sfSigningTime, signTime); if (naSeed.isValid()) setValueFieldVL(sfSigningKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic()); if (!isFull) setFlag(sFullFlag); @@ -50,9 +50,9 @@ uint256 SerializedValidation::getLedgerHash() const return getValueFieldH256(sfLedgerHash); } -uint32 SerializedValidation::getCloseTime() const +uint32 SerializedValidation::getSignTime() const { - return getValueFieldU32(sfCloseTime); + return getValueFieldU32(sfSigningTime); } uint32 SerializedValidation::getFlags() const diff --git a/src/SerializedValidation.h b/src/SerializedValidation.h index dddd1fdce6..81e4c1d6e1 100644 --- a/src/SerializedValidation.h +++ b/src/SerializedValidation.h @@ -13,7 +13,8 @@ protected: void setNode(); public: - typedef boost::shared_ptr pointer; + typedef boost::shared_ptr pointer; + typedef const boost::shared_ptr& ref; static SOElement sValidationFormat[16]; static const uint32 sFullFlag; @@ -22,10 +23,10 @@ public: SerializedValidation(SerializerIterator& sit, bool checkSignature = true); SerializedValidation(const Serializer& s, bool checkSignature = true); - SerializedValidation(const uint256& ledgerHash, uint32 closeTime, const NewcoinAddress& naSeed, bool isFull); + SerializedValidation(const uint256& ledgerHash, uint32 signTime, const NewcoinAddress& naSeed, bool isFull); uint256 getLedgerHash() const; - uint32 getCloseTime() const; + uint32 getSignTime() const; uint32 getFlags() const; NewcoinAddress getSignerPublic() const; bool isValid() const; diff --git a/src/Suppression.cpp b/src/Suppression.cpp index c285d5f349..4b7cad5711 100644 --- a/src/Suppression.cpp +++ b/src/Suppression.cpp @@ -1,6 +1,7 @@ - #include "Suppression.h" +#include + bool SuppressionTable::addSuppression(const uint160& suppression) { boost::mutex::scoped_lock sl(mSuppressionMutex); @@ -9,15 +10,16 @@ bool SuppressionTable::addSuppression(const uint160& suppression) return false; time_t now = time(NULL); + time_t expireTime = now - mHoldTime; - boost::unordered_map< time_t, std::list >::iterator it = mSuppressionTimes.begin(); - while (it != mSuppressionTimes.end()) + boost::unordered_map< time_t, std::list >::iterator + it = mSuppressionTimes.begin(), end = mSuppressionTimes.end(); + while (it != end) { - if ((it->first + mHoldTime) < now) + if (it->first <= expireTime) { - for (std::list::iterator lit = it->second.begin(), end = it->second.end(); - lit != end; ++lit) - mSuppressionMap.erase(*lit); + BOOST_FOREACH(const uint160& lit, it->second) + mSuppressionMap.erase(lit); it = mSuppressionTimes.erase(it); } else ++it; diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index f1718518e0..c710775406 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -3155,7 +3155,7 @@ TER PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint } PathState::PathState( - const Ledger::pointer& lpLedger, + Ledger::ref lpLedger, const int iIndex, const LedgerEntrySet& lesSource, const STPath& spSourcePath, diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index d2e7cd4016..cb913dd44f 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -230,7 +230,7 @@ public: STAmount saOutAct; // Amount actually sent (calc output). PathState( - const Ledger::pointer& lpLedger, + Ledger::ref lpLedger, const int iIndex, const LedgerEntrySet& lesSource, const STPath& spSourcePath, @@ -243,7 +243,7 @@ public: Json::Value getJson() const; static PathState::pointer createPathState( - const Ledger::pointer& lpLedger, + Ledger::ref lpLedger, const int iIndex, const LedgerEntrySet& lesSource, const STPath& spSourcePath, @@ -382,10 +382,10 @@ protected: public: TransactionEngine() { ; } - TransactionEngine(const Ledger::pointer& ledger) : mLedger(ledger) { assert(mLedger); } + TransactionEngine(Ledger::ref ledger) : mLedger(ledger) { assert(mLedger); } - Ledger::pointer getLedger() { return mLedger; } - void setLedger(const Ledger::pointer& ledger) { assert(ledger); mLedger = ledger; } + Ledger::pointer getLedger() { return mLedger; } + void setLedger(Ledger::ref ledger) { assert(ledger); mLedger = ledger; } TER applyTransaction(const SerializedTransaction&, TransactionEngineParams); }; diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index 0dee29b63e..b6d109777c 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -17,7 +17,7 @@ bool ValidationCollection::addValidation(const SerializedValidation::pointer& va { val->setTrusted(); uint32 now = theApp->getOPs().getCloseTimeNC(); - uint32 valClose = val->getCloseTime(); + uint32 valClose = val->getSignTime(); if ((now > (valClose - LEDGER_EARLY_INTERVAL)) && (now < (valClose + LEDGER_VAL_INTERVAL))) isCurrent = true; else @@ -34,27 +34,21 @@ bool ValidationCollection::addValidation(const SerializedValidation::pointer& va return false; if (isCurrent) { - boost::unordered_map::iterator it = mCurrentValidations.find(node); - if ((it == mCurrentValidations.end()) || (!it->second.newest) || - (val->getCloseTime() > it->second.newest->getCloseTime())) + boost::unordered_map::iterator it = mCurrentValidations.find(node); + if (it == mCurrentValidations.end()) + mCurrentValidations.insert(std::make_pair(node, val)); + else if (!it->second) + it->second = val; + else if (val->getSignTime() > it->second->getSignTime()) { - if (it != mCurrentValidations.end()) - { - if (it->second.oldest) - { - mStaleValidations.push_back(it->second.oldest); - condWrite(); - } - it->second.oldest = it->second.newest; - it->second.newest = val; - } - else - mCurrentValidations.insert(std::make_pair(node, ValidationPair(val))); + mStaleValidations.push_back(it->second); + it->second = val; + condWrite(); } } } - Log(lsINFO) << "Val for " << hash.GetHex() << " from " << signer.humanNodePublic() + Log(lsINFO) << "Val for " << hash << " from " << signer.humanNodePublic() << " added " << (val->isTrusted() ? "trusted/" : "UNtrusted/") << (isCurrent ? "current" : "stale"); return isCurrent; } @@ -76,7 +70,7 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren trusted = untrusted = 0; boost::mutex::scoped_lock sl(mValidationLock); boost::unordered_map::iterator it = mValidations.find(ledger); - uint32 now = theApp->getOPs().getCloseTimeNC(); + uint32 now = theApp->getOPs().getNetworkTimeNC(); if (it != mValidations.end()) { for (ValidationSet::iterator vit = it->second.begin(), end = it->second.end(); vit != end; ++vit) @@ -84,13 +78,13 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren bool isTrusted = vit->second->isTrusted(); if (isTrusted && currentOnly) { - uint32 closeTime = vit->second->getCloseTime(); + uint32 closeTime = vit->second->getSignTime(); if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL))) isTrusted = false; else { #ifdef VC_DEBUG - Log(lsINFO) << "VC: Untrusted due to time " << ledger.GetHex(); + Log(lsINFO) << "VC: Untrusted due to time " << ledger; #endif } } @@ -101,7 +95,7 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren } } #ifdef VC_DEBUG - Log(lsINFO) << "VC: " << ledger.GetHex() << "t:" << trusted << " u:" << untrusted; + Log(lsINFO) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted; #endif } @@ -125,10 +119,10 @@ int ValidationCollection::getCurrentValidationCount(uint32 afterTime) { int count = 0; boost::mutex::scoped_lock sl(mValidationLock); - for (boost::unordered_map::iterator it = mCurrentValidations.begin(), + for (boost::unordered_map::iterator it = mCurrentValidations.begin(), end = mCurrentValidations.end(); it != end; ++it) { - if (it->second.newest->isTrusted() && (it->second.newest->getCloseTime() > afterTime)) + if (it->second->isTrusted() && (it->second->getSignTime() > afterTime)) ++count; } return count; @@ -136,54 +130,26 @@ int ValidationCollection::getCurrentValidationCount(uint32 afterTime) boost::unordered_map ValidationCollection::getCurrentValidations() { - uint32 now = theApp->getOPs().getCloseTimeNC(); + uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL; boost::unordered_map ret; { boost::mutex::scoped_lock sl(mValidationLock); - boost::unordered_map::iterator it = mCurrentValidations.begin(); + boost::unordered_map::iterator it = mCurrentValidations.begin(); while (it != mCurrentValidations.end()) { - ValidationPair& pair = it->second; - - if (pair.oldest && (now > (pair.oldest->getCloseTime() + LEDGER_VAL_INTERVAL))) - { -#ifdef VC_DEBUG - Log(lsINFO) << "VC: " << it->first.GetHex() << " removeOldestStale"; -#endif - mStaleValidations.push_back(pair.oldest); - pair.oldest = SerializedValidation::pointer(); - condWrite(); - } - if (pair.newest && (now > (pair.newest->getCloseTime() + LEDGER_VAL_INTERVAL))) - { -#ifdef VC_DEBUG - Log(lsINFO) << "VC: " << it->first.GetHex() << " removeNewestStale"; -#endif - mStaleValidations.push_back(pair.newest); - pair.newest = SerializedValidation::pointer(); - condWrite(); - } - if (!pair.newest && !pair.oldest) + if (!it->second) // contains no record it = mCurrentValidations.erase(it); + else if (it->second->getSignTime() < cutoff) + { // contains a stale record + mStaleValidations.push_back(it->second); + it->second = SerializedValidation::pointer(); + condWrite(); + it = mCurrentValidations.erase(it); + } else - { - if (pair.oldest) - { -#ifdef VC_DEBUG - Log(lsTRACE) << "VC: OLD " << pair.oldest->getLedgerHash().GetHex() << " " << - boost::lexical_cast(pair.oldest->getCloseTime()); -#endif - ++ret[pair.oldest->getLedgerHash()]; - } - if (pair.newest) - { -#ifdef VC_DEBUG - Log(lsTRACE) << "VC: NEW " << pair.newest->getLedgerHash().GetHex() << " " << - boost::lexical_cast(pair.newest->getCloseTime()); -#endif - ++ret[pair.newest->getLedgerHash()]; - } + { // contains a live record + ++ret[it->second->getLedgerHash()]; ++it; } } @@ -213,14 +179,12 @@ void ValidationCollection::addDeadLedger(const uint256& ledger) void ValidationCollection::flush() { boost::mutex::scoped_lock sl(mValidationLock); - boost::unordered_map::iterator it = mCurrentValidations.begin(); + boost::unordered_map::iterator it = mCurrentValidations.begin(); bool anyNew = false; while (it != mCurrentValidations.end()) { - if (it->second.oldest) - mStaleValidations.push_back(it->second.oldest); - if (it->second.newest) - mStaleValidations.push_back(it->second.newest); + if (it->second) + mStaleValidations.push_back(it->second); ++it; anyNew = true; } @@ -247,7 +211,7 @@ void ValidationCollection::condWrite() void ValidationCollection::doWrite() { static boost::format insVal("INSERT INTO LedgerValidations " - "(LedgerHash,NodePubKey,Flags,CloseTime,Signature) VALUES ('%s','%s','%u','%u',%s);"); + "(LedgerHash,NodePubKey,Flags,SignTime,Signature) VALUES ('%s','%s','%u','%u',%s);"); boost::mutex::scoped_lock sl(mValidationLock); assert(mWriting); @@ -265,7 +229,7 @@ void ValidationCollection::doWrite() BOOST_FOREACH(const SerializedValidation::pointer& it, vector) db->executeSQL(boost::str(insVal % it->getLedgerHash().GetHex() - % it->getSignerPublic().humanNodePublic() % it->getFlags() % it->getCloseTime() + % it->getSignerPublic().humanNodePublic() % it->getFlags() % it->getSignTime() % db->escape(strCopy(it->getSignature())))); db->executeSQL("END TRANSACTION;"); } diff --git a/src/ValidationCollection.h b/src/ValidationCollection.h index bdd224a040..4a5912abfe 100644 --- a/src/ValidationCollection.h +++ b/src/ValidationCollection.h @@ -12,23 +12,15 @@ typedef boost::unordered_map ValidationSet; -class ValidationPair -{ -public: - SerializedValidation::pointer oldest, newest; - - ValidationPair(const SerializedValidation::pointer& v) : newest(v) { ; } -}; - class ValidationCollection { protected: boost::mutex mValidationLock; - boost::unordered_map mValidations; - boost::unordered_map mCurrentValidations; - std::vector mStaleValidations; - std::list mDeadLedgers; + boost::unordered_map mValidations; + boost::unordered_map mCurrentValidations; + std::vector mStaleValidations; + std::list mDeadLedgers; bool mWriting; diff --git a/src/newcoin.proto b/src/newcoin.proto index 79f517468f..2426f16ece 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -107,8 +107,9 @@ message TMProposeSet { required bytes nodePubKey = 3; required uint32 closeTime = 4; required bytes signature = 5; // signature of above fields - repeated bytes addedTransactions = 6; // not required if number is large - repeated bytes removedTransactions = 7; // not required if number is large + optional bytes previousledger = 6; + repeated bytes addedTransactions = 10; // not required if number is large + repeated bytes removedTransactions = 11; // not required if number is large } enum TxSetStatus { diff --git a/src/uint256.h b/src/uint256.h index a5cb8c456a..bb11b101b4 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -278,7 +278,7 @@ public: std::string ToString() const { - return (GetHex()); + return GetHex(); } unsigned char* begin() @@ -559,6 +559,11 @@ inline const uint256 operator&(const uint256& a, const uint256& b) { return (b inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } extern std::size_t hash_value(const uint256&); +template inline std::ostream& operator<<(std::ostream& out, const base_uint& u) +{ + return out << u.GetHex(); +} + inline int Testuint256AdHoc(std::vector vArg) { uint256 g(0);