From 390e628f102e4ac0c09e490b7f23cdf283fba47f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 7 Sep 2012 15:06:25 -0700 Subject: [PATCH 01/10] Cmall cleanups and fixes. --- src/HashedObject.cpp | 6 ++---- src/Ledger.cpp | 2 +- src/LedgerConsensus.cpp | 8 +++----- src/SNTPClient.h | 4 +++- src/SerializedTypes.h | 5 ++++- src/TaggedCache.h | 2 +- src/TransactionEngine.cpp | 1 - src/TransactionEngine.h | 1 - 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/HashedObject.cpp b/src/HashedObject.cpp index f5717e879a..56f26e3d60 100644 --- a/src/HashedObject.cpp +++ b/src/HashedObject.cpp @@ -104,8 +104,6 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) sql.append(hash.GetHex()); sql.append("';"); - std::string type; - uint32 index; std::vector data; { ScopedLock sl(theApp->getHashNodeDB()->getDBLock()); @@ -121,7 +119,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) db->getStr("ObjType", type); if (type.size() == 0) return HashedObject::pointer(); - index = db->getBigInt("LedgerIndex"); + uint32 index = db->getBigInt("LedgerIndex"); int size = db->getBinary("Object", NULL, 0); data.resize(size); @@ -131,7 +129,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) assert(Serializer::getSHA512Half(data) == hash); HashedObjectType htype = UNKNOWN; - switch(type[0]) + switch (type[0]) { case 'L': htype = LEDGER; break; case 'T': htype = TRANSACTION; break; diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 08fd23cd7a..0e558747c0 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -154,7 +154,7 @@ void Ledger::setAccepted(uint32 closeTime, int closeResolution, bool correctClos void Ledger::setAccepted() { // used when we acquired the ledger - assert(mClosed && (mCloseResolution != 0) && (mCloseResolution != 0)); + assert(mClosed && (mCloseTime != 0) && (mCloseResolution != 0)); mCloseTime -= mCloseTime % mCloseResolution; updateHash(); mAccepted = true; diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 8ecccdcd87..4fc94ad785 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -209,12 +209,10 @@ bool LCTransaction::updatePosition(int percentTime, bool proposing) } 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) + : mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger), + mValSeed(theConfig.VALIDATION_SEED), mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false), + mConsensusStartTime(boost::posix_time::microsec_clock::universal_time()) { - mValSeed = theConfig.VALIDATION_SEED; - mConsensusStartTime = boost::posix_time::microsec_clock::universal_time(); - Log(lsDEBUG) << "Creating consensus object"; Log(lsTRACE) << "LCL:" << previousLedger->getHash() <<", ct=" << closeTime; mPreviousProposers = theApp->getOPs().getPreviousProposers(); diff --git a/src/SNTPClient.h b/src/SNTPClient.h index c2bf75ec63..ea01bcf7aa 100644 --- a/src/SNTPClient.h +++ b/src/SNTPClient.h @@ -9,12 +9,14 @@ #include #include +#include "types.h" + class SNTPQuery { public: bool mReceivedReply; time_t mLocalTimeSent; - int mQueryNonce; + uint32 mQueryNonce; SNTPQuery(time_t j = (time_t) -1) : mReceivedReply(false), mLocalTimeSent(j) { ; } }; diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 98461f5444..17e79af3c1 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -582,7 +582,10 @@ public: const uint160& getIssuerID() const { return mIssuerID; } bool operator==(const STPathElement& t) const - { return mType == t.mType && mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && mIssuerID == mIssuerID; } + { + return mType == t.mType && mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && + mIssuerID == t.mIssuerID; + } }; class STPath diff --git a/src/TaggedCache.h b/src/TaggedCache.h index 92a122d017..fb31a157b5 100644 --- a/src/TaggedCache.h +++ b/src/TaggedCache.h @@ -111,7 +111,7 @@ template void TaggedCache::sweep if (mit->second->expired()) { typename boost::unordered_map::iterator tmp = mit++; - mMap.erase(mit); + mMap.erase(mit++); } else ++mit; diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 2b690bb422..ebb97d517d 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -961,7 +961,6 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, { Log(lsTRACE) << "applyTransaction>"; assert(mLedger); - mLedgerParentCloseTime = mLedger->getParentCloseTimeNC(); mNodes.init(txn.getTransactionID(), mLedger->getLedgerSeq()); #ifdef DEBUG diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 1f4d493d5e..7f7d653cca 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -295,7 +295,6 @@ private: protected: Ledger::pointer mLedger; - uint64 mLedgerParentCloseTime; uint160 mTxnAccountID; SLE::pointer mTxnAccount; From cbc758db6427f6af8ea83db91b77ef63e4f84e5d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 7 Sep 2012 15:25:47 -0700 Subject: [PATCH 02/10] Fix crash --- src/LedgerConsensus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 4fc94ad785..bdba1c7da4 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -319,7 +319,7 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) BOOST_FOREACH(Peer::ref peer, peerList) mAcquiringLedger->peerHas(peer); } - if (mHaveCorrectLCL && mProposing) + if (mHaveCorrectLCL && mProposing && mOurPosition) { Log(lsINFO) << "Bowing out of consensus"; mOurPosition->bowOut(); From 0defc8d5abaee48a05f129fb55d9b5ada8e353ab Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 7 Sep 2012 15:50:07 -0700 Subject: [PATCH 03/10] Cleanups. --- src/UniqueNodeList.cpp | 8 ++++---- src/UniqueNodeList.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index 708a4f5e94..05453b0128 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -779,7 +779,7 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str } // Given a section with IPs, parse and persist it for a validator. -void UniqueNodeList::responseIps(const std::string& strSite, const NewcoinAddress& naNodePublic, const boost::system::error_code& err, const std::string strIpsFile) +void UniqueNodeList::responseIps(const std::string& strSite, const NewcoinAddress& naNodePublic, const boost::system::error_code& err, const std::string& strIpsFile) { if (!err) { @@ -819,7 +819,7 @@ void UniqueNodeList::getIpsUrl(const NewcoinAddress& naNodePublic, section secSi } // After fetching a newcoin.txt from a web site, given a section with validators, parse and persist it. -void UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, const NewcoinAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile) +void UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, const NewcoinAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string& strValidatorsFile) { if (!err) { @@ -858,7 +858,7 @@ void UniqueNodeList::getValidatorsUrl(const NewcoinAddress& naNodePublic, sectio } // Process a newcoin.txt. -void UniqueNodeList::processFile(const std::string strDomain, const NewcoinAddress& naNodePublic, section secSite) +void UniqueNodeList::processFile(const std::string& strDomain, const NewcoinAddress& naNodePublic, section secSite) { // // Process Validators @@ -885,7 +885,7 @@ void UniqueNodeList::processFile(const std::string strDomain, const NewcoinAddre } // Given a newcoin.txt, process it. -void UniqueNodeList::responseFetch(const std::string strDomain, const boost::system::error_code& err, const std::string strSiteFile) +void UniqueNodeList::responseFetch(const std::string& strDomain, const boost::system::error_code& err, const std::string& strSiteFile) { section secSite = ParseSection(strSiteFile, true); bool bGood = !err; diff --git a/src/UniqueNodeList.h b/src/UniqueNodeList.h index 1de853c960..667cbe92aa 100644 --- a/src/UniqueNodeList.h +++ b/src/UniqueNodeList.h @@ -95,7 +95,7 @@ private: bool scoreRound(std::vector& vsnNodes); - void responseFetch(const std::string strDomain, const boost::system::error_code& err, const std::string strSiteFile); + void responseFetch(const std::string& strDomain, const boost::system::error_code& err, const std::string& strSiteFile); boost::posix_time::ptime mtpScoreNext; // When to start scoring. boost::posix_time::ptime mtpScoreStart; // Time currently started scoring. @@ -119,13 +119,13 @@ private: void getValidatorsUrl(const NewcoinAddress& naNodePublic, section secSite); void getIpsUrl(const NewcoinAddress& naNodePublic, section secSite); - void responseIps(const std::string& strSite, const NewcoinAddress& naNodePublic, const boost::system::error_code& err, const std::string strIpsFile); - void responseValidators(const std::string& strValidatorsUrl, const NewcoinAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile); + void responseIps(const std::string& strSite, const NewcoinAddress& naNodePublic, const boost::system::error_code& err, const std::string& strIpsFile); + void responseValidators(const std::string& strValidatorsUrl, const NewcoinAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string& strValidatorsFile); void processIps(const std::string& strSite, const NewcoinAddress& naNodePublic, section::mapped_type* pmtVecStrIps); int processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, validatorSource vsWhy, section::mapped_type* pmtVecStrValidators); - void processFile(const std::string strDomain, const NewcoinAddress& naNodePublic, section secSite); + void processFile(const std::string& strDomain, const NewcoinAddress& naNodePublic, section secSite); bool getSeedDomains(const std::string& strDomain, seedDomain& dstSeedDomain); void setSeedDomains(const seedDomain& dstSeedDomain, bool bNext); From 63921c975701b1b4357239185e8c3bb1e3410779 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 7 Sep 2012 22:21:07 -0700 Subject: [PATCH 04/10] Cleanups and fixes. --- src/HashedObject.cpp | 20 ++++++++++---------- src/HashedObject.h | 10 +++++----- src/Ledger.cpp | 4 ++-- src/LedgerAcquire.cpp | 2 +- src/SHAMapSync.h | 5 +++-- src/TransactionMeta.h | 2 +- src/UniqueNodeList.cpp | 11 ++++------- src/Wallet.cpp | 6 ++---- 8 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/HashedObject.cpp b/src/HashedObject.cpp index 56f26e3d60..69e855ddc6 100644 --- a/src/HashedObject.cpp +++ b/src/HashedObject.cpp @@ -71,11 +71,11 @@ void HashedObjectStore::bulkWrite() char type; switch(it->getType()) { - case LEDGER: type = 'L'; break; - case TRANSACTION: type = 'T'; break; - case ACCOUNT_NODE: type = 'A'; break; - case TRANSACTION_NODE: type = 'N'; break; - default: type = 'U'; + case hotLEDGER: type= 'L'; break; + case hotTRANSACTION: type = 'T'; break; + case hotACCOUNT_NODE: type = 'A'; break; + case hotTRANSACTION_NODE: type = 'N'; break; + default: type = 'U'; } std::string rawData; db->escape(&(it->getData().front()), it->getData().size(), rawData); @@ -128,13 +128,13 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash) assert(Serializer::getSHA512Half(data) == hash); - HashedObjectType htype = UNKNOWN; + HashedObjectType htype = hotUNKNOWN; switch (type[0]) { - case 'L': htype = LEDGER; break; - case 'T': htype = TRANSACTION; break; - case 'A': htype = ACCOUNT_NODE; break; - case 'N': htype = TRANSACTION_NODE; break; + case 'L': htype = hotLEDGER; break; + case 'T': htype = hotTRANSACTION; break; + case 'A': htype = hotACCOUNT_NODE; break; + case 'N': htype = hotTRANSACTION_NODE; break; default: Log(lsERROR) << "Invalid hashed object"; return HashedObject::pointer(); diff --git a/src/HashedObject.h b/src/HashedObject.h index 0331cfa9b3..f403d5042a 100644 --- a/src/HashedObject.h +++ b/src/HashedObject.h @@ -10,11 +10,11 @@ enum HashedObjectType { - UNKNOWN = 0, - LEDGER = 1, - TRANSACTION = 2, - ACCOUNT_NODE = 3, - TRANSACTION_NODE = 4 + hotUNKNOWN = 0, + hotLEDGER = 1, + hotTRANSACTION = 2, + hotACCOUNT_NODE = 3, + hotTRANSACTION_NODE = 4 }; class HashedObject diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 0e558747c0..9b36e003b8 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -279,9 +279,9 @@ void Ledger::saveAcceptedLedger(Ledger::ref ledger) ledger->mAccountHash.GetHex() % ledger->mTransHash.GetHex())); // write out dirty nodes - while(ledger->mTransactionMap->flushDirty(256, TRANSACTION_NODE, ledger->mLedgerSeq)) + while(ledger->mTransactionMap->flushDirty(256, hotTRANSACTION_NODE, ledger->mLedgerSeq)) { ; } - while(ledger->mAccountStateMap->flushDirty(256, ACCOUNT_NODE, ledger->mLedgerSeq)) + while(ledger->mAccountStateMap->flushDirty(256, hotACCOUNT_NODE, ledger->mLedgerSeq)) { ; } ledger->disarmDirty(); diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index 177dfa6dd6..a9a6263426 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -310,7 +310,7 @@ bool LedgerAcquire::takeBase(const std::string& data) Serializer s(data.size() + 4); s.add32(sHP_Ledger); s.addRaw(data); - theApp->getHashedObjectStore().store(LEDGER, mLedger->getLedgerSeq(), s.peekData(), mHash); + theApp->getHashedObjectStore().store(hotLEDGER, mLedger->getLedgerSeq(), s.peekData(), mHash); progress(); if (!mLedger->getTransHash()) diff --git a/src/SHAMapSync.h b/src/SHAMapSync.h index 2cd6ffc1e4..3d673e37a3 100644 --- a/src/SHAMapSync.h +++ b/src/SHAMapSync.h @@ -37,7 +37,7 @@ public: virtual void gotNode(const SHAMapNode& id, const uint256& nodeHash, const std::vector& nodeData, bool isLeaf) { - theApp->getHashedObjectStore().store(ACCOUNT_NODE, mLedgerSeq, nodeData, nodeHash); + theApp->getHashedObjectStore().store(hotACCOUNT_NODE, mLedgerSeq, nodeData, nodeHash); } virtual bool haveNode(const SHAMapNode& id, const uint256& nodeHash, std::vector& nodeData) { // fetchNodeExternal already tried @@ -58,7 +58,8 @@ public: virtual void gotNode(const SHAMapNode& id, const uint256& nodeHash, const std::vector& nodeData, bool isLeaf) { - theApp->getHashedObjectStore().store(isLeaf ? TRANSACTION : TRANSACTION_NODE, mLedgerSeq, nodeData, nodeHash); + theApp->getHashedObjectStore().store(isLeaf ? hotTRANSACTION : hotTRANSACTION_NODE, mLedgerSeq, + nodeData, nodeHash); } virtual bool haveNode(const SHAMapNode& id, const uint256& nodeHash, std::vector& nodeData) { // fetchNodeExternal already tried diff --git a/src/TransactionMeta.h b/src/TransactionMeta.h index eecc70bfb4..729a724808 100644 --- a/src/TransactionMeta.h +++ b/src/TransactionMeta.h @@ -71,7 +71,7 @@ protected: uint32 mPrevLgrSeq; public: - TMNEThread() : TransactionMetaNodeEntry(TMSThread) { ; } + TMNEThread() : TransactionMetaNodeEntry(TMSThread), mPrevLgrSeq(0) { ; } TMNEThread(uint256 prevTx, uint32 prevLgrSeq) : TransactionMetaNodeEntry(TMSThread), mPrevTxID(prevTx), mPrevLgrSeq(prevLgrSeq) { ; } diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index 05453b0128..b5b1d2c804 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -184,8 +184,6 @@ void UniqueNodeList::scoreCompute() Database* db=theApp->getWalletDB()->getDB(); - std::string strSql; - // For each entry in SeedDomains with a PublicKey: // - Add an entry in umPulicIdx, umDomainIdx, and vsnNodes. { @@ -389,7 +387,7 @@ void UniqueNodeList::scoreCompute() db->executeSQL("BEGIN;"); db->executeSQL("UPDATE TrustedNodes SET Score = 0 WHERE Score != 0;"); - if (vsnNodes.size()) + if (!vsnNodes.empty()) { // Load existing Seens from DB. std::vector vstrPublicKeys; @@ -410,7 +408,7 @@ void UniqueNodeList::scoreCompute() boost::unordered_set usUNL; - if (vsnNodes.size()) + if (!vsnNodes.empty()) { // Update the score old entries and add new entries as needed. std::vector vstrValues; @@ -446,7 +444,7 @@ void UniqueNodeList::scoreCompute() boost::unordered_map umValidators; - if (vsnNodes.size()) + if (!vsnNodes.empty()) { std::vector vstrPublicKeys; @@ -627,7 +625,7 @@ void UniqueNodeList::processIps(const std::string& strSite, const NewcoinAddress } // Add new referral entries. - if (pmtVecStrIps && pmtVecStrIps->size()) { + if (pmtVecStrIps && !pmtVecStrIps->empty()) { std::vector vstrValues; vstrValues.resize(MIN(pmtVecStrIps->size(), REFERRAL_IPS_MAX)); @@ -712,7 +710,6 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str break; boost::smatch smMatch; - std::string strIP; // domain comment? // public_key comment? diff --git a/src/Wallet.cpp b/src/Wallet.cpp index 5d1ef4e8a7..f5670eda73 100644 --- a/src/Wallet.cpp +++ b/src/Wallet.cpp @@ -16,8 +16,8 @@ #include "Application.h" #include "utils.h" -Wallet::Wallet() : mLedger(0) { -} +Wallet::Wallet() : mDh512(NULL), mDh1024(NULL), mLedger(0) +{ ; } void Wallet::start() { @@ -136,8 +136,6 @@ bool Wallet::dataFetch(const std::string& strKey, std::string& strValue) if (db->executeSQL(str(boost::format("SELECT Value FROM RPCData WHERE Key=%s;") % db->escape(strKey))) && db->startIterRows()) { - std::string strPublicKey, strPrivateKey; - std::vector vucData = db->getBinary("Value"); strValue.assign(vucData.begin(), vucData.end()); From 1a1952ea7b3c8fe813fa92a505aad655c435ac66 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 8 Sep 2012 00:48:26 -0700 Subject: [PATCH 05/10] You can now create a LedgerEntrySet without a TransactionEngine. You can call all the various entry* functions on it directly. You can throw it out when you're done. The constructor is: LedgerEntrySet(Ledger::ref ledger) All the normal checkpointing, caching, and swapping will work. Of course, you cannot commit the results. The TransactionEngine::entry* functions now just directly call the corresponding functions on the LedgerEntrySet. You can call them in code that will only be used in the context of a transaction. --- src/LedgerEntrySet.cpp | 48 ++++++++++++++++++++++++++++---------- src/LedgerEntrySet.h | 18 ++++++++++---- src/TransactionEngine.cpp | 49 ++------------------------------------- src/TransactionEngine.h | 8 +++---- 4 files changed, 55 insertions(+), 68 deletions(-) diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index 2f31478bd2..5b5b703e66 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -2,9 +2,10 @@ #include -void LedgerEntrySet::init(const uint256& transactionID, uint32 ledgerID) +void LedgerEntrySet::init(Ledger::ref ledger, const uint256& transactionID, uint32 ledgerID) { mEntries.clear(); + mLedger = ledger; mSet.init(transactionID, ledgerID); mSeq = 0; } @@ -17,7 +18,7 @@ void LedgerEntrySet::clear() LedgerEntrySet LedgerEntrySet::duplicate() const { - return LedgerEntrySet(mEntries, mSet, mSeq + 1); + return LedgerEntrySet(mLedger, mEntries, mSet, mSeq + 1); } void LedgerEntrySet::setTo(const LedgerEntrySet& e) @@ -25,11 +26,13 @@ void LedgerEntrySet::setTo(const LedgerEntrySet& e) mEntries = e.mEntries; mSet = e.mSet; mSeq = e.mSeq; + mLedger = e.mLedger; } void LedgerEntrySet::swapWith(LedgerEntrySet& e) { std::swap(mSeq, e.mSeq); + std::swap(mLedger, e.mLedger); mSet.swap(e.mSet); mEntries.swap(e.mEntries); } @@ -53,6 +56,36 @@ SLE::pointer LedgerEntrySet::getEntry(const uint256& index, LedgerEntryAction& a return it->second.mEntry; } +SLE::pointer LedgerEntrySet::entryCreate(LedgerEntryType letType, const uint256& index) +{ + assert(index.isNonZero()); + SLE::pointer sleNew = boost::make_shared(letType); + sleNew->setIndex(index); + entryCreate(sleNew); + return sleNew; +} + +SLE::pointer LedgerEntrySet::entryCache(LedgerEntryType letType, const uint256& index) +{ + SLE::pointer sleEntry; + if (index.isNonZero()) + { + LedgerEntryAction action; + sleEntry = getEntry(index, action); + if (!sleEntry) + { + sleEntry = mLedger->getSLE(index); + if (sleEntry) + entryCache(sleEntry); + } + else if (action == taaDELETE) + { + assert(false); + } + } + return sleEntry; +} + LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const { boost::unordered_map::const_iterator it = mEntries.find(index); @@ -147,7 +180,7 @@ void LedgerEntrySet::entryModify(SLE::ref sle) } } -void LedgerEntrySet::entryDelete(SLE::ref sle, bool unfunded) +void LedgerEntrySet::entryDelete(SLE::ref sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -166,15 +199,6 @@ void LedgerEntrySet::entryDelete(SLE::ref sle, bool unfunded) it->second.mSeq = mSeq; it->second.mEntry = sle; it->second.mAction = taaDELETE; - if (unfunded) - { - assert(sle->getType() == ltOFFER); // only offers can be unfunded -#if 0 - mSet.deleteUnfunded(sle->getIndex(), - sle->getIValueFieldAmount(sfTakerPays), - sle->getIValueFieldAmount(sfTakerGets)); -#endif - } break; case taaCREATE: diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index 0ab19896b9..c840057c27 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -31,12 +31,13 @@ public: class LedgerEntrySet { protected: + Ledger::pointer mLedger; boost::unordered_map mEntries; TransactionMetaSet mSet; int mSeq; - LedgerEntrySet(const boost::unordered_map &e, const TransactionMetaSet& s, int m) : - mEntries(e), mSet(s), mSeq(m) { ; } + LedgerEntrySet(Ledger::ref ledger, const boost::unordered_map &e, + const TransactionMetaSet& s, int m) : mLedger(ledger), mEntries(e), mSet(s), mSeq(m) { ; } SLE::pointer getForMod(const uint256& node, Ledger::ref ledger, boost::unordered_map& newMods); @@ -51,6 +52,9 @@ protected: boost::unordered_map& newMods); public: + + LedgerEntrySet(Ledger::ref ledger) : mLedger(ledger), mSeq(0) { ; } + LedgerEntrySet() : mSeq(0) { ; } // set functions @@ -60,7 +64,7 @@ public: int getSeq() const { return mSeq; } void bumpSeq() { ++mSeq; } - void init(const uint256& transactionID, uint32 ledgerID); + void init(Ledger::ref ledger, const uint256& transactionID, uint32 ledgerID); void clear(); // basic entry functions @@ -68,14 +72,18 @@ public: LedgerEntryAction hasEntry(const uint256& index) const; 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 entryDelete(SLE::ref); // This entry will be deleted void entryModify(SLE::ref); // This entry will be modified + // higher-level ledger functions + SLE::pointer entryCreate(LedgerEntryType letType, const uint256& uIndex); + SLE::pointer entryCache(LedgerEntryType letType, const uint256& uIndex); + Json::Value getJson(int) const; void calcRawMeta(Serializer&, Ledger::ref originalLedger); // iterator functions - bool isEmpty() const { return mEntries.empty(); } + bool isEmpty() const { return mEntries.empty(); } boost::unordered_map::const_iterator begin() const { return mEntries.begin(); } boost::unordered_map::const_iterator end() const { return mEntries.end(); } boost::unordered_map::iterator begin() { return mEntries.begin(); } diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 74d5467ea5..4c57195192 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -865,50 +865,6 @@ TER TransactionEngine::setAuthorized(const SerializedTransaction& txn, bool bMus return tesSUCCESS; } -SLE::pointer TransactionEngine::entryCache(LedgerEntryType letType, const uint256& uIndex) -{ - SLE::pointer sleEntry; - - if (!!uIndex) - { - LedgerEntryAction action; - sleEntry = mNodes.getEntry(uIndex, action); - if (!sleEntry) - { - sleEntry = mLedger->getSLE(uIndex); - if (sleEntry) - mNodes.entryCache(sleEntry); - } - else if (action == taaDELETE) - { - assert(false); - } - } - - return sleEntry; -} - -SLE::pointer TransactionEngine::entryCreate(LedgerEntryType letType, const uint256& uIndex) -{ - assert(!!uIndex); - - SLE::pointer sleNew = boost::make_shared(letType); - sleNew->setIndex(uIndex); - mNodes.entryCreate(sleNew); - - return sleNew; -} - -void TransactionEngine::entryDelete(SLE::pointer sleEntry, bool bUnfunded) -{ - mNodes.entryDelete(sleEntry, bUnfunded); -} - -void TransactionEngine::entryModify(SLE::pointer sleEntry) -{ - mNodes.entryModify(sleEntry); -} - void TransactionEngine::txnWrite() { // Write back the account states and add the transaction to the ledger @@ -956,12 +912,11 @@ void TransactionEngine::txnWrite() } } -TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, - TransactionEngineParams params) +TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params) { Log(lsTRACE) << "applyTransaction>"; assert(mLedger); - mNodes.init(txn.getTransactionID(), mLedger->getLedgerSeq()); + mNodes.init(mLedger, txn.getTransactionID(), mLedger->getLedgerSeq()); #ifdef DEBUG if (1) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 7f7d653cca..b164ea2b01 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -308,10 +308,10 @@ protected: // If the transaction fails to meet some constraint, still need to delete unfunded offers. boost::unordered_set musUnfundedFound; // Offers that were found unfunded. - SLE::pointer entryCreate(LedgerEntryType letType, const uint256& uIndex); - SLE::pointer entryCache(LedgerEntryType letType, const uint256& uIndex); - void entryDelete(SLE::pointer sleEntry, bool bUnfunded = false); - void entryModify(SLE::pointer sleEntry); + SLE::pointer entryCreate(LedgerEntryType type, const uint256& index) { return mNodes.entryCreate(type, index); } + SLE::pointer entryCache(LedgerEntryType type, const uint256& index) { return mNodes.entryCache(type, index); } + void entryDelete(SLE::ref sleEntry) { mNodes.entryDelete(sleEntry); } + void entryModify(SLE::ref sleEntry) { mNodes.entryModify(sleEntry); } TER offerDelete(const uint256& uOfferIndex); TER offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID); From e2137ea5af8de50f66dce7047bb00c6e1dbac561 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 8 Sep 2012 03:49:12 -0700 Subject: [PATCH 06/10] Make our ledger a bit stickier to avoid the "check at the wrong time" problem (when you don't have enough validations for the latest ledger and so jump backwards when you shouldn't. This solves every known ledger consensus issue except the "stuck one ledger behind" issue. I'm working on that now. --- src/LedgerConsensus.cpp | 5 +---- src/NetworkOPs.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index bdba1c7da4..802810f681 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -247,10 +247,7 @@ void LedgerConsensus::checkLCL() uint256 netLgr = mPrevLedgerHash; int netLgrCount = 0; - uint256 favorLedger; - if (mState != lcsPRE_CLOSE) - favorLedger = mPrevLedgerHash; - boost::unordered_map vals = theApp->getValidations().getCurrentValidations(favorLedger); + boost::unordered_map vals = theApp->getValidations().getCurrentValidations(mPrevLedgerHash); typedef std::pair u256_int_pair; BOOST_FOREACH(u256_int_pair& it, vals) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 7706cd7ac9..754559db83 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -446,18 +446,18 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector& peerLis // node is using. THis is kind of fundamental. Log(lsTRACE) << "NetworkOPs::checkLastClosedLedger"; - boost::unordered_map ledgers; + Ledger::pointer ourClosed = mLedgerMaster->getClosedLedger(); + uint256 closedLedger = ourClosed->getHash(); + uint256 prevClosedLedger = ourClosed->getParentHash(); + boost::unordered_map ledgers; { - boost::unordered_map current = theApp->getValidations().getCurrentValidations(); + boost::unordered_map current = theApp->getValidations().getCurrentValidations(closedLedger); typedef std::pair u256_int_pair; BOOST_FOREACH(u256_int_pair& it, current) ledgers[it.first].trustedValidations += it.second; } - Ledger::pointer ourClosed = mLedgerMaster->getClosedLedger(); - uint256 closedLedger = ourClosed->getHash(); - uint256 prevClosedLedger = ourClosed->getParentHash(); ValidationCount& ourVC = ledgers[closedLedger]; if ((theConfig.LEDGER_CREATOR) && (mMode >= omTRACKING)) From 9222eee1df973db85be26596afeb9ee366a6ed42 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 8 Sep 2012 03:51:56 -0700 Subject: [PATCH 07/10] I believe this trivial change solves the "stuck one ledger behind" problem. If the ledger is open, there should be no significant number of proposals for a subsequent ledger. If there is, we are a ledger behind. --- src/LedgerConsensus.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 802810f681..5a4c27341c 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -247,6 +247,7 @@ void LedgerConsensus::checkLCL() uint256 netLgr = mPrevLedgerHash; int netLgrCount = 0; + uint256 favoredLedger = (mState == PRE_CLOSE) ? uint256() : mPrevLedgerHash; // Don't get stuck one ledger behind boost::unordered_map vals = theApp->getValidations().getCurrentValidations(mPrevLedgerHash); typedef std::pair u256_int_pair; From 18b18359c591b9efc90724995e20b9119785c46b Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 8 Sep 2012 04:14:06 -0700 Subject: [PATCH 08/10] Be smarter about tracking which peers have which ledgers. --- src/Peer.cpp | 20 +++++++++++++++++++- src/Peer.h | 5 ++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index 27db8ff017..aec3ce31e2 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -649,7 +649,10 @@ void Peer::recvHello(newcoin::TMHello& packet) { memcpy(mClosedLedgerHash.begin(), packet.ledgerclosed().data(), 256 / 8); if ((packet.has_ledgerprevious()) && (packet.ledgerprevious().size() == (256 / 8))) + { memcpy(mPreviousLedgerHash.begin(), packet.ledgerprevious().data(), 256 / 8); + addLedger(mPreviousLedgerHash); + } else mPreviousLedgerHash.zero(); } @@ -915,6 +918,7 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet) if (packet.has_ledgerhash() && (packet.ledgerhash().size() == (256 / 8))) { // a peer has changed ledgers memcpy(mClosedLedgerHash.begin(), packet.ledgerhash().data(), 256 / 8); + addLedger(mClosedLedgerHash); Log(lsTRACE) << "peer LCL is " << mClosedLedgerHash << " " << getIP(); } else @@ -926,6 +930,7 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet) if (packet.has_ledgerhashprevious() && packet.ledgerhashprevious().size() == (256 / 8)) { memcpy(mPreviousLedgerHash.begin(), packet.ledgerhashprevious().data(), 256 / 8); + addLedger(mPreviousLedgerHash); } else mPreviousLedgerHash.zero(); } @@ -1134,7 +1139,20 @@ void Peer::recvLedger(newcoin::TMLedgerData& packet) bool Peer::hasLedger(const uint256& hash) const { - return (hash == mClosedLedgerHash) || (hash == mPreviousLedgerHash); + BOOST_FOREACH(const uint256& ledger, mRecentLedgers) + if (ledger == hash) + return true; + return false; +} + +void Peer::addLedger(const uint256& hash) +{ + BOOST_FOREACH(const uint256& ledger, mRecentLedgers) + if (ledger == hash) + return; + if (mRecentLedgers.size() == 16) + mRecentLedgers.pop_front(); + mRecentLedgers.push_back(hash); } // Get session information we can sign to prevent man in the middle attack. diff --git a/src/Peer.h b/src/Peer.h index 13c5fdb2de..ae4abf7307 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -44,7 +44,8 @@ private: ipPort mIpPortConnect; uint256 mCookieHash; - uint256 mClosedLedgerHash, mPreviousLedgerHash; + uint256 mClosedLedgerHash, mPreviousLedgerHash; + std::list mRecentLedgers; boost::asio::ssl::stream mSocketSsl; @@ -116,6 +117,8 @@ protected: void getSessionCookie(std::string& strDst); + void addLedger(const uint256& ledger); + public: //bool operator == (const Peer& other); From 3ab5b24226d140f665c5acf5713f8deec913eb71 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 8 Sep 2012 04:14:26 -0700 Subject: [PATCH 09/10] Trivial change. --- src/LedgerAcquire.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index a9a6263426..353b7d8872 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -405,7 +405,8 @@ LedgerAcquire::pointer LedgerAcquireMaster::findCreate(const uint256& hash) assert(hash.isNonZero()); boost::mutex::scoped_lock sl(mLock); LedgerAcquire::pointer& ptr = mLedgers[hash]; - if (ptr) return ptr; + if (ptr) + return ptr; ptr = boost::make_shared(hash); assert(mLedgers[hash] == ptr); ptr->resetTimer(); // Cannot call in constructor @@ -417,7 +418,8 @@ LedgerAcquire::pointer LedgerAcquireMaster::find(const uint256& hash) assert(hash.isNonZero()); boost::mutex::scoped_lock sl(mLock); std::map::iterator it = mLedgers.find(hash); - if (it != mLedgers.end()) return it->second; + if (it != mLedgers.end()) + return it->second; return LedgerAcquire::pointer(); } From 4271a9d12d54cc4674dd45501b95f3ff45ed3252 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 8 Sep 2012 04:14:42 -0700 Subject: [PATCH 10/10] Improve comments. Fix a typo in previous commit. --- src/LedgerConsensus.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 5a4c27341c..ce064fe47c 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -59,7 +59,8 @@ void TransactionAcquire::trigger(Peer::ref peer, bool timer) } else { - std::vector nodeIDs; std::vector nodeHashes; + std::vector nodeIDs; + std::vector nodeHashes; ConsensusTransSetSF sf; mMap->getMissingNodes(nodeIDs, nodeHashes, 256, &sf); if (nodeIDs.empty()) @@ -68,6 +69,8 @@ void TransactionAcquire::trigger(Peer::ref peer, bool timer) mComplete = true; else mFailed = true; + done(); + return; } else { @@ -77,12 +80,9 @@ void TransactionAcquire::trigger(Peer::ref peer, bool timer) for (std::vector::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it) *(tmGL.add_nodeids()) = it->getRawString(); sendRequest(tmGL, peer); - return; } } - if (mComplete || mFailed) - done(); - else if (timer) + if (timer) resetTimer(); } @@ -128,7 +128,7 @@ bool TransactionAcquire::takeNodes(const std::list& nodeIDs, } void LCTransaction::setVote(const uint160& peer, bool votesYes) -{ +{ // Tracke a peer's yes/no vote on a particular disputed transaction std::pair::iterator, bool> res = mVotes.insert(std::make_pair(peer, votesYes)); @@ -162,7 +162,7 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes) } void LCTransaction::unVote(const uint160& peer) -{ +{ // Remove a peer's vote on this disputed transasction boost::unordered_map::iterator it = mVotes.find(peer); if (it != mVotes.end()) { @@ -175,7 +175,7 @@ void LCTransaction::unVote(const uint160& peer) } bool LCTransaction::updatePosition(int percentTime, bool proposing) -{ // this many seconds after close, should our position change +{ if (mOurPosition && (mNays == 0)) return false; if (!mOurPosition && (mYays == 0)) @@ -247,29 +247,28 @@ void LedgerConsensus::checkLCL() uint256 netLgr = mPrevLedgerHash; int netLgrCount = 0; - uint256 favoredLedger = (mState == PRE_CLOSE) ? uint256() : mPrevLedgerHash; // Don't get stuck one ledger behind - boost::unordered_map vals = theApp->getValidations().getCurrentValidations(mPrevLedgerHash); + uint256 favoredLedger = (mState == lcsPRE_CLOSE) ? uint256() : mPrevLedgerHash; // Don't get stuck one ledger behind + boost::unordered_map vals = + theApp->getValidations().getCurrentValidations(favoredLedger); typedef std::pair u256_int_pair; BOOST_FOREACH(u256_int_pair& it, vals) - { if (it.second > netLgrCount) { netLgr = it.first; netLgrCount = it.second; } - } if (netLgr != mPrevLedgerHash) { // LCL change const char *status; switch (mState) { - case lcsPRE_CLOSE: status="PreClose"; break; - case lcsESTABLISH: status="Establish"; break; - case lcsFINISHED: status="Finised"; break; - case lcsACCEPTED: status="Accepted"; break; - default: status="unknown"; + case lcsPRE_CLOSE: status = "PreClose"; break; + case lcsESTABLISH: status = "Establish"; break; + case lcsFINISHED: status = "Finised"; break; + case lcsACCEPTED: status = "Accepted"; break; + default: status = "unknown"; } Log(lsWARNING) << "View of consensus changed during consensus (" << netLgrCount << ") status=" @@ -301,8 +300,10 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) else { Log(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash; + mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(mPrevLedgerHash); std::vector peerList = theApp->getConnectionPool().getPeerVector(); + bool found = false; BOOST_FOREACH(Peer::ref peer, peerList) { @@ -312,11 +313,13 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) mAcquiringLedger->peerHas(peer); } } + if (!found) { BOOST_FOREACH(Peer::ref peer, peerList) mAcquiringLedger->peerHas(peer); } + if (mHaveCorrectLCL && mProposing && mOurPosition) { Log(lsINFO) << "Bowing out of consensus";