From 8f88030219f912d96f85f67e79144bc6ace41afe Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 09:23:01 -0700 Subject: [PATCH 01/22] Log whether we processed a peer ledger proposal or not. --- src/LedgerConsensus.cpp | 2 +- src/NetworkOPs.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index b93875ea5a..8056144078 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -516,7 +516,7 @@ bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition) return true; } } - Log(lsINFO) << "Peer position " << newPosition->getProposeSeq() << "/" + Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" << newPosition->getCurrentHash().GetHex(); currentPosition = newPosition; SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 6dd381171c..d0b182db13 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -489,7 +489,11 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, // Is this node on our UNL? // XXX Is this right? if (!theApp->getUNL().nodeInUNL(naPeerPublic)) + { + Log(lsINFO) << "Relay, but no process peer proposal " << proposal->getProposeSeq() << "/" + << proposal->getCurrentHash().GetHex(); return true; + } return consensus->peerPosition(proposal); } From 2ff19d65e81ececde7e310b1cc3f2cda1698deb9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 09:52:06 -0700 Subject: [PATCH 02/22] Don't go to full (validating) if we don't have a validation seed. --- src/NetworkOPs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index d0b182db13..479cbb35ab 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -392,7 +392,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result) // check if the ledger is good enough to go to omFULL // Note: Do not go to omFULL if we don't have the previous ledger // check if the ledger is bad enough to go to omCONNECTED -- TODO - if (!switchLedgers) setMode(omFULL); + if ((!switchLedgers) && theConfig.VALIDATION_SEED.isValid()) setMode(omFULL); } if (mMode == omFULL) From 36b829f003faa38476088cdeba1973bc27bb571a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 09:52:49 -0700 Subject: [PATCH 03/22] Don't bork Nagle. --- src/Peer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index 72d2719531..83c7377c26 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -184,7 +184,6 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip { std::cerr << "Connect peer: success." << std::endl; - mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true)); mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none); mSocketSsl.async_handshake(boost::asio::ssl::stream::client, @@ -224,7 +223,6 @@ void Peer::connected(const boost::system::error_code& error) mIpPort = make_pair(strIp, iPort); assert(!mIpPort.first.empty()); - mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true)); mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none); mSocketSsl.async_handshake(boost::asio::ssl::stream::server, From 7e286839bb6205e2c12e21a4b841a69d0842833e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 10:30:10 -0700 Subject: [PATCH 04/22] Suppress SQL errors in two cases where they are normal. --- src/Ledger.cpp | 2 +- src/Transaction.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index aa57d69373..f0e9d5f376 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -292,7 +292,7 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger) } sql += ";"; Log(lsTRACE) << "ActTx: " << sql; - db->executeSQL(sql); + db->executeSQL(sql, true); // may already be in there if (!db->executeSQL( txn.getSQLInsertHeader() + txn.getSQL(ledger->getLedgerSeq(), TXN_SQL_VALIDATED) + ";"), true) { // transaction already in DB, update diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 355a6a2fa5..5a3b87e42b 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -525,7 +525,8 @@ bool Transaction::save() Database *db = theApp->getTxnDB()->getDB(); ScopedLock dbLock = theApp->getTxnDB()->getDBLock(); - return db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";"); + return + db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";", true); } Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) From 8277854a1598500580fbb8d4119bd5fff54b1fec Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 10:37:05 -0700 Subject: [PATCH 05/22] Fix SQL error. --- src/DBInit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 7406ce2ce4..8c6931e3b6 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -228,7 +228,7 @@ int WalletDBCount = sizeof(WalletDBInit) / sizeof(const char *); // Hash node database holds nodes indexed by hash const char *HashNodeDBInit[] = { - "CREATE TABLE CommittedObjects \ + "CREATE TABLE CommittedObjects ( \ Hash CHARACTER(64) PRIMARY KEY, \ ObjType CHAR(1) NOT NULL, \ LedgerIndex BIGINT UNSIGNED, \ From ec9308bbb87e9c0c9a14e9d83b07a5544a33c901 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 10:37:11 -0700 Subject: [PATCH 06/22] Cleanups. --- src/HashedObject.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/HashedObject.cpp b/src/HashedObject.cpp index fd2aa94ef7..68a7512b3b 100644 --- a/src/HashedObject.cpp +++ b/src/HashedObject.cpp @@ -1,10 +1,11 @@ +#include "HashedObject.h" + #include -#include "HashedObject.h" #include "Serializer.h" #include "Application.h" - +#include "Log.h" bool HashedObject::checkHash() const @@ -26,16 +27,6 @@ void HashedObject::setHash() mHash = Serializer::getSHA512Half(mData); } -/* -CREATE TABLE CommittedObjects ( -- used to synch nodes - Hash BLOB PRIMARY KEY, - ObjType CHAR(1) NOT NULL, -- (L)edger, (T)ransaction, (A)ccount node, transaction (N)ode - LedgerIndex BIGINT UNSIGNED, -- 0 if none - Object BLOB -); -CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType); -*/ - // FIXME: Stores should be added to a queue that's services by an auxilliary thread or from an // auxilliary thread pool. These should be tied into a cache, since you need one to handle // an immedate read back (before the write completes) @@ -117,6 +108,9 @@ HashedObject::pointer HashedObject::retrieve(const uint256& hash) case 'T': htype = TRANSACTION; break; case 'A': htype = ACCOUNT_NODE; break; case 'N': htype = TRANSACTION_NODE; break; + default: + Log(lsERROR) << "Invalid hashed object"; + return HashedObject::pointer(); } HashedObject::pointer obj = boost::make_shared(htype, index, data); From 2a28428409c895439a44830fc3c1e6bc85bc9014 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 10:56:26 -0700 Subject: [PATCH 07/22] Add SQL_EXISTS macro to check if an entry exists. --- database/database.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/database.h b/database/database.h index 835aa99c36..50b247b4f3 100644 --- a/database/database.h +++ b/database/database.h @@ -10,6 +10,9 @@ if ((_db)->executeSQL(_strQuery)) \ for (bool _bMore = (_db)->startIterRows(); _bMore; _bMore = (_db)->getNextRow()) +#define SQL_EXISTS(_db, _strQuery) \ + ((_db)->executeSQL(_strQuery) && (_db)->startIterRows()) + /* this maintains the connection to the database */ From 95ea30085c0801202e5673596d862c713cedf463 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 10:56:55 -0700 Subject: [PATCH 08/22] Remove chatty debug. --- src/LedgerConsensus.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 8056144078..35dd29c1f9 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -48,7 +48,6 @@ void TransactionAcquire::trigger(Peer::pointer peer) } if (mHaveRoot) { - Log(lsTRACE) << "Have root"; std::vector nodeIDs; std::vector nodeHashes; mMap->getMissingNodes(nodeIDs, nodeHashes, 256, &mFilter); From 62dfd40ce984b18267409ba9e47a3b24d565772d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 10:57:10 -0700 Subject: [PATCH 09/22] Make SQL updates more sane. --- src/Ledger.cpp | 58 ++++++++++++++++++++++++++------------------- src/Transaction.cpp | 6 ++++- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index f0e9d5f376..753f238726 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -270,36 +270,46 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger) { SerializerIterator sit(item->peekSerializer()); SerializedTransaction txn(sit); - std::vector accts = txn.getAffectedAccounts(); - - std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES "; - bool first = true; - for (std::vector::iterator it = accts.begin(), end = accts.end(); it != end; ++it) + if (!SQL_EXISTS(db, + boost::str(boost::format("SELECT LedgerSeq FROM AccountTransactions WHERE TransId = '%s';") + % item->getTag().GetHex()))) { - if (!first) - sql += ", ('"; - else + std::vector accts = txn.getAffectedAccounts(); + + std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES "; + bool first = true; + for (std::vector::iterator it = accts.begin(), end = accts.end(); it != end; ++it) { - sql += "('"; - first = false; + if (!first) + sql += ", ('"; + else + { + sql += "('"; + first = false; + } + sql += txn.getTransactionID().GetHex(); + sql += "','"; + sql += it->humanAccountID(); + sql += "',"; + sql += boost::lexical_cast(ledger->getLedgerSeq()); + sql += ")"; } - sql += txn.getTransactionID().GetHex(); - sql += "','"; - sql += it->humanAccountID(); - sql += "',"; - sql += boost::lexical_cast(ledger->getLedgerSeq()); - sql += ")"; + sql += ";"; + Log(lsTRACE) << "ActTx: " << sql; + db->executeSQL(sql); // may already be in there } - sql += ";"; - Log(lsTRACE) << "ActTx: " << sql; - db->executeSQL(sql, true); // may already be in there - if (!db->executeSQL( - txn.getSQLInsertHeader() + txn.getSQL(ledger->getLedgerSeq(), TXN_SQL_VALIDATED) + ";"), true) - { // transaction already in DB, update - db->executeSQL(boost::str(boost::format( - "UPDATE Transactions SET LedgerSeq = '%d', Status = '%c' WHERE TransID = '%s';") % + if (SQL_EXISTS(db, boost::str(boost::format("SELECT Status from Transactions where TransID = '%s';") % + txn.getTransactionID().GetHex()))) + { + db->executeSQL(boost::str( + boost::format("UPDATE Transactions SET LedgerSeq = '%d', Status = '%c' WHERE TransID = '%s';") % ledger->getLedgerSeq() % TXN_SQL_VALIDATED % txn.getTransactionID().GetHex())); } + else + { + db->executeSQL( + txn.getSQLInsertHeader() + txn.getSQL(ledger->getLedgerSeq(), TXN_SQL_VALIDATED) + ";"); + } } db->executeSQL("COMMIT TRANSACTION;"); } diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 5a3b87e42b..934304195e 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -523,10 +523,14 @@ bool Transaction::save() default: status = TXN_SQL_UNKNOWN; } + std::string exists = boost::str(boost::format("SELECT Status FROM Transactions WHERE TransID = '%s';") + % mTransaction->getTransactionID().GetHex()); + Database *db = theApp->getTxnDB()->getDB(); ScopedLock dbLock = theApp->getTxnDB()->getDBLock(); + if (!SQL_EXISTS(db, exists)) return false; return - db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";", true); + db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";"); } Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) From 195c37b7c21cb7836229ef4b051e2a0c067e13bb Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:05:28 -0700 Subject: [PATCH 10/22] Fix another one. --- src/Ledger.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 753f238726..3424fb2f64 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -236,6 +236,7 @@ uint256 Ledger::getHash() void Ledger::saveAcceptedLedger(Ledger::pointer ledger) { + std::string sql="INSERT INTO Ledgers " "(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,AccountSetHash,TransSetHash) VALUES ('"; sql.append(ledger->getHash().GetHex()); @@ -254,6 +255,13 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger) sql.append("');"); ScopedLock sl(theApp->getLedgerDB()->getDBLock()); + if (SQL_EXISTS(theApp->getLedgerDB()->getDB(), + boost::str(boost::format("SELECT LedgerSeq FROM Ledgers where LedgerSeq = '%d';") % ledger->mLedgerSeq) + )) + { + theApp->getLedgerDB()->getDB()->executeSQL( + boost::str(boost::format("DELETE FROM Ledgers WHERE LedgerSeq = '%d';") % ledger->mLedgerSeq)); + } theApp->getLedgerDB()->getDB()->executeSQL(sql); // write out dirty nodes From 844e3ed95f1a6afd7218c11c16ce7cff9ea8ab1b Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 18 Jun 2012 11:05:32 -0700 Subject: [PATCH 11/22] Remove BOOST_LOG_TRIVIAL. --- src/RPCServer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 7bdc257c9d..f663219ee0 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -92,8 +92,6 @@ Json::Value RPCServer::RPCError(int iError) void RPCServer::connected() { - - //BOOST_LOG_TRIVIAL(info) << "RPC request"; //std::cout << "RPC request" << std::endl; mSocket.async_read_some(boost::asio::buffer(mReadBuffer), From 3b4208f8fc589f9199e68e4c7e02fb9abb4940a2 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:07:10 -0700 Subject: [PATCH 12/22] Log which node we got from cache. --- src/SHAMapSync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SHAMapSync.cpp b/src/SHAMapSync.cpp index d0af0c44d4..089ca444b4 100644 --- a/src/SHAMapSync.cpp +++ b/src/SHAMapSync.cpp @@ -60,7 +60,7 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vectorgetString(); mTNByID[*d] = d; } } From 0dd5e0776ddad218269b70dc41b99a068b5d131c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:18:52 -0700 Subject: [PATCH 13/22] Extra logging. --- src/LedgerConsensus.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 35dd29c1f9..749641c118 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -39,7 +39,6 @@ void TransactionAcquire::trigger(Peer::pointer peer) return; if (!mHaveRoot) { - Log(lsTRACE) << "Don't have root"; newcoin::TMGetLedger tmGL; tmGL.set_ledgerhash(mHash.begin(), mHash.size()); tmGL.set_itype(newcoin::liTS_CANDIDATE); @@ -125,18 +124,26 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes) if (res.second) { // new vote if (votesYes) + { + Log(lsTRACE) << "Peer " << peer.GetHex() << "votes YES on " << mTransactionID.GetHex(); ++mYays; + } else + { + Log(lsTRACE) << "Peer " << peer.GetHex() << "votes NO on " << mTransactionID.GetHex(); ++mNays; + } } else if (votesYes && !res.first->second) { // changes vote to yes + Log(lsTRACE) << "Peer " << peer.GetHex() << "now votes YES on " << mTransactionID.GetHex(); --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(); ++mNays; --mYays; res.first->second = false; @@ -160,6 +167,7 @@ bool LCTransaction::updatePosition(int seconds) if (newPosition == mOurPosition) return false; mOurPosition = newPosition; + Log(lsTRACE) << "We now vote " << (mOurPosition ? "YES" : "NO") << " on " << mTransactionID.GetHex(); return true; } @@ -200,16 +208,16 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) if (!map) { // this is an invalid/corrupt map mComplete[hash] = map; + Log(lsWARNING) << "A trusted node directed us to acquire an invalid TXN map"; return; } - mAcquiring.erase(hash); - if (mComplete.find(hash) != mComplete.end()) { Log(lsERROR) << "Which we already had"; return; // we already have this map } + if (mOurPosition && (map->getHash() != mOurPosition->getCurrentHash())) { // this could create disputed transactions boost::unordered_map::iterator it2 = mComplete.find(mOurPosition->getCurrentHash()); @@ -241,6 +249,8 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) } if (!peers.empty()) adjustCount(map, peers); + else + Log(lsWARNING) << "By the time we got the map, no peers were proposing it"; sendHaveTxSet(hash, true); } From afd3d39d673fdd670c8a495becc86bb080451493 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:20:21 -0700 Subject: [PATCH 14/22] Prettify. --- src/LedgerConsensus.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 749641c118..40fefa74bc 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -125,25 +125,25 @@ 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.GetHex() << " votes YES on " << mTransactionID.GetHex(); ++mYays; } else { - Log(lsTRACE) << "Peer " << peer.GetHex() << "votes NO on " << mTransactionID.GetHex(); + Log(lsTRACE) << "Peer " << peer.GetHex() << " votes NO on " << mTransactionID.GetHex(); ++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.GetHex() << " now votes YES on " << mTransactionID.GetHex(); --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.GetHex() << " now votes NO on " << mTransactionID.GetHex(); ++mNays; --mYays; res.first->second = false; From 098bbcfe7f3b81d99596e066144692078b2bff17 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:21:38 -0700 Subject: [PATCH 15/22] Remove chatty debug --- src/LedgerAcquire.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index eb3769edad..be389a4eb1 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -105,7 +105,7 @@ void LedgerAcquire::addOnComplete(boost::function void LedgerAcquire::trigger(Peer::pointer peer) { -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "Trigger acquiring ledger " << mHash.GetHex() << std::endl; std::cerr << "complete=" << mComplete << " failed=" << mFailed << std::endl; std::cerr << "base=" << mHaveBase << " tx=" << mHaveTransactions << " as=" << mHaveState << std::endl; @@ -114,7 +114,7 @@ void LedgerAcquire::trigger(Peer::pointer peer) return; if (!mHaveBase) { -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "need base" << std::endl; #endif newcoin::TMGetLedger tmGL; @@ -130,7 +130,7 @@ void LedgerAcquire::trigger(Peer::pointer peer) if (mHaveBase && !mHaveTransactions) { -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "need tx" << std::endl; #endif assert(mLedger); @@ -182,7 +182,7 @@ void LedgerAcquire::trigger(Peer::pointer peer) if (mHaveBase && !mHaveState) { -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "need as" << std::endl; #endif assert(mLedger); @@ -267,7 +267,7 @@ void PeerSet::sendRequest(const newcoin::TMGetLedger& tmGL) bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer) { // Return value: true=normal, false=bad data -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "got base acquiring ledger " << mHash.GetHex() << std::endl; #endif boost::recursive_mutex::scoped_lock sl(mLock); @@ -275,10 +275,8 @@ bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer) mLedger = boost::make_shared(data); if (mLedger->getHash() != mHash) { -#ifdef DEBUG std::cerr << "Acquire hash mismatch" << std::endl; std::cerr << mLedger->getHash().GetHex() << "!=" << mHash.GetHex() << std::endl; -#endif mLedger = Ledger::pointer(); return false; } @@ -320,7 +318,7 @@ bool LedgerAcquire::takeTxNode(const std::list& nodeIDs, bool LedgerAcquire::takeAsNode(const std::list& nodeIDs, const std::list< std::vector >& data, Peer::pointer peer) { -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "got ASdata acquiring ledger " << mHash.GetHex() << std::endl; #endif if (!mHaveBase) return false; @@ -380,19 +378,17 @@ bool LedgerAcquireMaster::dropLedger(const uint256& hash) bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer peer) { -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << "got data for acquiring ledger "; #endif uint256 hash; if (packet.ledgerhash().size() != 32) { -#ifdef DEBUG - std::cerr << "error" << std::endl; -#endif + std::cerr << "Acquire error" << std::endl; return false; } memcpy(hash.begin(), packet.ledgerhash().data(), 32); -#ifdef DEBUG +#ifdef LA_DEBUG std::cerr << hash.GetHex() << std::endl; #endif From 03bbf8d41a8f6842def9d8424c8184e50cac43ca Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:22:04 -0700 Subject: [PATCH 16/22] Cleanup. --- src/Peer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index 83c7377c26..a81196b140 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -826,7 +826,6 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) return; } memcpy(ledgerhash.begin(), packet.ledgerhash().data(), 32); - Log(lsINFO) << "Query by hash: " << ledgerhash.GetHex(); ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash); } else if (packet.has_ledgerseq()) @@ -911,7 +910,6 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) } if (packet.has_requestcookie()) reply.set_requestcookie(packet.requestcookie()); PackedMessage::pointer oPacket = boost::make_shared(reply, newcoin::mtLEDGER_DATA); - Log(lsTRACE) << "sending reply"; sendPacket(oPacket); } From 0e47edbdfe01fdeb3f730a932459a96c2ba887f0 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:43:34 -0700 Subject: [PATCH 17/22] Fix some consensus bugs. --- src/LedgerConsensus.cpp | 52 +++++++++++++++++++++++++++++++++-------- src/LedgerTiming.h | 15 ++++++++---- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 40fefa74bc..c21ca0138b 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -13,6 +13,8 @@ #define TRUST_NETWORK +// #define LC_DEBUG + TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mFilter(&theApp->getNodeCache()), mHaveRoot(false) { @@ -152,20 +154,40 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes) bool LCTransaction::updatePosition(int seconds) { // this many seconds after close, should our position change - - if (mOurPosition && (mNays == 0)) return false; - if (!mOurPosition && (mYays == 0)) return false; +#ifdef LC_DEBUG + Log(lsTRACE) << "Checking our position on " << mTransactionID.GetHex(); +#endif + if (mOurPosition && (mNays == 0)) + { +#ifdef LC_DEBUG + Log(lsTRACE) << "YES and no NOs"; +#endif + return false; + } + if (!mOurPosition && (mYays == 0)) + { +#ifdef LC_DEBUG + Log(lsTRACE) << "NO and no YESes"; +#endif + return false; + } // This is basically the percentage of nodes voting 'yes' (including us) int weight = (mYays * 100 + (mOurPosition ? 100 : 0)) / (mNays + mYays + 1); // To prevent avalanche stalls, we increase the needed weight slightly over time bool newPosition; - if (seconds <= LEDGER_CONVERGE) newPosition = weight > AV_MIN_CONSENSUS; - else if (seconds >= LEDGER_FORCE_CONVERGE) newPosition = weight > AV_MAX_CONSENSUS; + if (seconds <= LEDGER_ACCEL_CONVERGE) newPosition = weight > AV_MIN_CONSENSUS; + else if (seconds >= LEDGER_CONVERGE) newPosition = weight > AV_MAX_CONSENSUS; else newPosition = weight > AV_AVG_CONSENSUS; - if (newPosition == mOurPosition) return false; + if (newPosition == mOurPosition) + { +#ifdef LC_DEBUG + Log(lsTRACE) << "No change: weight " << weight; +#endif + return false; + } mOurPosition = newPosition; Log(lsTRACE) << "We now vote " << (mOurPosition ? "YES" : "NO") << " on " << mTransactionID.GetHex(); return true; @@ -228,10 +250,17 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) it2->second->compare(map, differences, 16384); for(SHAMap::SHAMapDiff::iterator pos = differences.begin(), end = differences.end(); pos != end; ++pos) { // create disputed transactions (from the ledger that has them) + Log(lsTRACE) << "Transaction now in dispute: " << pos->first.GetHex(); if (pos->second.first) + { + assert(!pos->second.second); addDisputedTransaction(pos->first, pos->second.first->peekData()); + } else if(pos->second.second) + { + assert(!pos->second.first); addDisputedTransaction(pos->first, pos->second.second->peekData()); + } else assert(false); } } @@ -328,7 +357,7 @@ int LedgerConsensus::statePostClose(int secondsSinceClose) int LedgerConsensus::stateEstablish(int secondsSinceClose) { // we are establishing consensus updateOurPositions(secondsSinceClose); - if (secondsSinceClose > LEDGER_CONVERGE) + if (secondsSinceClose > LEDGER_MAX_CONVERGE) { Log(lsINFO) << "Converge cutoff"; mState = lcsCUTOFF; @@ -339,7 +368,7 @@ int LedgerConsensus::stateEstablish(int secondsSinceClose) int LedgerConsensus::stateCutoff(int secondsSinceClose) { // we are making sure everyone else agrees bool haveConsensus = updateOurPositions(secondsSinceClose); - if (haveConsensus || (secondsSinceClose > LEDGER_FORCE_CONVERGE)) + if (haveConsensus || (secondsSinceClose > LEDGER_CONVERGE)) { Log(lsINFO) << "Consensus complete (" << haveConsensus << ")"; mState = lcsFINISHED; @@ -385,6 +414,8 @@ bool LedgerConsensus::updateOurPositions(int sinceClose) SHAMap::pointer ourPosition; std::vector addedTx, removedTx; + + Log(lsTRACE) << "updating our positions"; for(boost::unordered_map::iterator it = mDisputes.begin(), end = mDisputes.end(); it != end; ++it) { @@ -413,11 +444,11 @@ bool LedgerConsensus::updateOurPositions(int sinceClose) if (changes) { - Log(lsINFO) << "We change our position"; uint256 newHash = ourPosition->getHash(); mOurPosition->changePosition(newHash); propose(addedTx, removedTx); - sendHaveTxSet(newHash, true); + sendHaveTxSet(newHash, true); // FIXME: This may be redundant + Log(lsINFO) << "We change our position to " << newHash.GetHex(); } return stable; @@ -482,6 +513,7 @@ void LedgerConsensus::propose(const std::vector& added, const std::vect void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vector& tx) { + Log(lsTRACE) << "Transacstion " << txID.GetHex() << " is disputed"; boost::unordered_map::iterator it = mDisputes.find(txID); if (it != mDisputes.end()) return; diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index 0d3bb04056..5a2793aa86 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -12,11 +12,15 @@ // Time before we take a position # define LEDGER_WOBBLE_TIME 1 -// Time we expect avalanche to finish +// Time we acceleratet avalanche +# define LEDGER_ACCEL_CONVERGE 10 + +// Time we permit avalanche to finish # define LEDGER_CONVERGE 14 -// Time we forcibly abort avalanche -# define LEDGER_FORCE_CONVERGE 18 +// Maximum converge time +# define LEDGER_MAX_CONVERGE 22 + #endif @@ -24,9 +28,10 @@ # define LEDGER_INTERVAL 1800 -# define LEDGER_CONVERGE 180 +# define LEDGER_FORCE_CONVERGE 180 + +# define LEDGER_CONVERGE 240 -# define LEDGER_FORCE_CONVERGE 240 // Time a transaction must be unconflicted before we consider it protected # define LEDGER_PROTECT 90 From b3bba6b2b0d858f57dd3fdf89bd769ab83be7836 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 11:44:40 -0700 Subject: [PATCH 18/22] Fix chatty debug. --- src/LedgerConsensus.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index c21ca0138b..83fcaccbd7 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -415,7 +415,9 @@ bool LedgerConsensus::updateOurPositions(int sinceClose) std::vector addedTx, removedTx; +#ifdef LC_DEBUG Log(lsTRACE) << "updating our positions"; +#endif for(boost::unordered_map::iterator it = mDisputes.begin(), end = mDisputes.end(); it != end; ++it) { From a0970e705f804d30edff60f850a695c85a993a83 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 12:24:15 -0700 Subject: [PATCH 19/22] Consensus bugfixing. --- src/LedgerConsensus.cpp | 82 +++++++++++++++++++++++++++-------------- src/LedgerConsensus.h | 1 + 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 83fcaccbd7..ace093399a 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "../json/writer.h" @@ -143,7 +144,7 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes) ++mYays; res.first->second = true; } - else if(!votesYes && !res.first->second) + else if(!votesYes && res.first->second) { // changes vote to no Log(lsTRACE) << "Peer " << peer.GetHex() << " now votes NO on " << mTransactionID.GetHex(); ++mNays; @@ -178,13 +179,14 @@ bool LCTransaction::updatePosition(int seconds) // To prevent avalanche stalls, we increase the needed weight slightly over time bool newPosition; if (seconds <= LEDGER_ACCEL_CONVERGE) newPosition = weight > AV_MIN_CONSENSUS; - else if (seconds >= LEDGER_CONVERGE) newPosition = weight > AV_MAX_CONSENSUS; - else newPosition = weight > AV_AVG_CONSENSUS; + else if (seconds >= LEDGER_CONVERGE) newPosition = weight > AV_AVG_CONSENSUS; + else newPosition = weight > AV_MAX_CONSENSUS; if (newPosition == mOurPosition) { #ifdef LC_DEBUG - Log(lsTRACE) << "No change: weight " << weight; + Log(lsTRACE) << "No change (" << (mOurPosition ? "YES" : "NO") << ") : weight " + << weight << ", seconds " << seconds; #endif return false; } @@ -204,24 +206,55 @@ LedgerConsensus::LedgerConsensus(Ledger::pointer previousLedger, uint32 closeTim { Log(lsDEBUG) << "Creating consensus object"; Log(lsTRACE) << "LCL:" << previousLedger->getHash().GetHex() <<", ct=" << closeTime; - - // we always have an empty map - mComplete[uint256()] = boost::make_shared(); } void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger) { - // XXX Don't even start if no VALIDATION_SEED. - SHAMap::pointer initialSet = initialLedger->peekTransactionMap()->snapShot(false); uint256 txSet = initialSet->getHash(); assert (initialLedger->getParentHash() == mPreviousLedger->getHash()); - mOurPosition = boost::make_shared(theConfig.VALIDATION_SEED, initialLedger->getParentHash(), txSet); + // if any peers have taken a contrary position, process disputes + boost::unordered_set found; + for(boost::unordered_map::iterator it = mPeerPositions.begin(), + end = mPeerPositions.end(); it != end; ++it) + { + uint256 set = it->second->getCurrentHash(); + if (found.insert(set).second) + { + boost::unordered_map::iterator it = mComplete.find(set); + if (it != mComplete.end()) + createDisputes(initialSet, it->second); + } + } + + mOurPosition = boost::make_shared + (theConfig.VALIDATION_SEED, initialLedger->getParentHash(), txSet); mapComplete(txSet, initialSet); propose(std::vector(), std::vector()); } +void LedgerConsensus::createDisputes(SHAMap::pointer m1, SHAMap::pointer m2) +{ + SHAMap::SHAMapDiff differences; + m1->compare(m2, differences, 16384); + for(SHAMap::SHAMapDiff::iterator pos = differences.begin(), end = differences.end(); pos != end; ++pos) + { // create disputed transactions (from the ledger that has them) + Log(lsTRACE) << "Transaction now in dispute: " << pos->first.GetHex(); + if (pos->second.first) + { + assert(!pos->second.second); + addDisputedTransaction(pos->first, pos->second.first->peekData()); + } + else if(pos->second.second) + { + assert(!pos->second.first); + addDisputedTransaction(pos->first, pos->second.second->peekData()); + } + else assert(false); + } +} + void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) { Log(lsINFO) << "We have acquired TXS " << hash.GetHex(); @@ -246,23 +279,7 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) if (it2 != mComplete.end()) { assert((it2->first == mOurPosition->getCurrentHash()) && it2->second); - SHAMap::SHAMapDiff differences; - it2->second->compare(map, differences, 16384); - for(SHAMap::SHAMapDiff::iterator pos = differences.begin(), end = differences.end(); pos != end; ++pos) - { // create disputed transactions (from the ledger that has them) - Log(lsTRACE) << "Transaction now in dispute: " << pos->first.GetHex(); - if (pos->second.first) - { - assert(!pos->second.second); - addDisputedTransaction(pos->first, pos->second.first->peekData()); - } - else if(pos->second.second) - { - assert(!pos->second.first); - addDisputedTransaction(pos->first, pos->second.second->peekData()); - } - else assert(false); - } + createDisputes(it2->second, map); } else assert(false); // We don't have our own position?! } @@ -449,7 +466,7 @@ bool LedgerConsensus::updateOurPositions(int sinceClose) uint256 newHash = ourPosition->getHash(); mOurPosition->changePosition(newHash); propose(addedTx, removedTx); - sendHaveTxSet(newHash, true); // FIXME: This may be redundant + mapComplete(newHash, ourPosition); Log(lsINFO) << "We change our position to " << newHash.GetHex(); } @@ -466,6 +483,12 @@ SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool do TransactionAcquire::pointer& acquiring = mAcquiring[hash]; if (!acquiring) { + if (!hash) + { + SHAMap::pointer empty = boost::make_shared(); + mapComplete(hash, empty); + return empty; + } acquiring = boost::make_shared(hash); startAcquiring(acquiring); } @@ -565,10 +588,12 @@ bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition) SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true); if (set) { + Log(lsTRACE) << "Have that set"; for (boost::unordered_map::iterator it = mDisputes.begin(), end = mDisputes.end(); it != end; ++it) it->second->setVote(newPosition->getPeerID(), set->hasItem(it->first)); } + else Log(lsTRACE) << "Don't have that set"; return true; } @@ -746,6 +771,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) ScopedLock sl = theApp->getMasterLedger().getLock(); applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, failedTransactions); + // FIXME: Apply disputed transactions not voted into the candidate set theApp->getMasterLedger().pushLedger(newLCL, newOL); mState = lcsACCEPTED; sl.unlock(); diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 3f3f422dee..721265c245 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -106,6 +106,7 @@ protected: void startAcquiring(TransactionAcquire::pointer); SHAMap::pointer find(const uint256& hash); + void createDisputes(SHAMap::pointer, SHAMap::pointer); void addDisputedTransaction(const uint256&, const std::vector& transaction); void adjustCount(SHAMap::pointer map, const std::vector& peers); void propose(const std::vector& addedTx, const std::vector& removedTx); From a46b43e3a561cfaedde33cfd57ba4aa7020d1865 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 12:49:02 -0700 Subject: [PATCH 20/22] Add a constructor --- src/SHAMap.cpp | 4 ++++ src/SHAMap.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp index ac600171e5..8811dcce67 100644 --- a/src/SHAMap.cpp +++ b/src/SHAMap.cpp @@ -228,6 +228,10 @@ SHAMapItem::SHAMapItem(const uint256& tag, const std::vector& dat : mTag(tag), mData(data) { ; } +SHAMapItem::SHAMapItem(const uint256& tag, const Serializer& data) + : mTag(tag), mData(data.peekData()) +{ ; } + SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node) { // Return the first item below this node diff --git a/src/SHAMap.h b/src/SHAMap.h index 0588096c7a..8851abbf1f 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -93,6 +93,7 @@ public: SHAMapItem(const uint256& tag) : mTag(tag) { ; } SHAMapItem(const uint256& tag, const std::vector& data); + SHAMapItem(const uint256& tag, const Serializer& s); SHAMapItem(const std::vector& data); // tag by hash const uint256& getTag() const { return mTag; } From 74ea434435363394a1b2d77120e8a0586828b96c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 12:57:43 -0700 Subject: [PATCH 21/22] Bugfixes to consensus: 1) Don't apply to new open ledger in final mode. 2) Re-apply any NO transactions to the new open ledger. --- src/LedgerConsensus.cpp | 105 ++++++++++++++++++++++++---------------- src/LedgerConsensus.h | 9 ++-- 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index ace093399a..a5ae65551b 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -155,23 +155,10 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes) bool LCTransaction::updatePosition(int seconds) { // this many seconds after close, should our position change -#ifdef LC_DEBUG - Log(lsTRACE) << "Checking our position on " << mTransactionID.GetHex(); -#endif if (mOurPosition && (mNays == 0)) - { -#ifdef LC_DEBUG - Log(lsTRACE) << "YES and no NOs"; -#endif return false; - } if (!mOurPosition && (mYays == 0)) - { -#ifdef LC_DEBUG - Log(lsTRACE) << "NO and no YESes"; -#endif return false; - } // This is basically the percentage of nodes voting 'yes' (including us) int weight = (mYays * 100 + (mOurPosition ? 100 : 0)) / (mNays + mYays + 1); @@ -431,10 +418,6 @@ bool LedgerConsensus::updateOurPositions(int sinceClose) SHAMap::pointer ourPosition; std::vector addedTx, removedTx; - -#ifdef LC_DEBUG - Log(lsTRACE) << "updating our positions"; -#endif for(boost::unordered_map::iterator it = mDisputes.begin(), end = mDisputes.end(); it != end; ++it) { @@ -643,9 +626,44 @@ void LedgerConsensus::Saccept(boost::shared_ptr This, SHAMap::p This->accept(txSet); } -void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger, - CanonicalTXSet& failedTransactions) +void LedgerConsensus::applyTransaction(TransactionEngine& engine, SerializedTransaction::pointer txn, + Ledger::pointer ledger, CanonicalTXSet& failedTransactions, bool final) { + TransactionEngineParams parms = final ? (tepNO_CHECK_FEE | tepUPDATE_TOTAL) : tepNONE; +#ifndef TRUST_NETWORK + try + { +#endif + TransactionEngineResult result = engine.applyTransaction(*txn, parms, 0); + if (result > 0) + { + Log(lsINFO) << " retry"; + assert(!ledger->hasTransaction(txn->getTransactionID())); + failedTransactions.push_back(txn); + } + else if (result == 0) + { + Log(lsDEBUG) << " success"; + assert(ledger->hasTransaction(txn->getTransactionID())); + } + else + { + Log(lsINFO) << " hard fail"; + assert(!ledger->hasTransaction(txn->getTransactionID())); + } +#ifndef TRUST_NETWORK + } + catch (...) + { + Log(lsWARNING) << " Throws"; + } +#endif +} + +void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger, + CanonicalTXSet& failedTransactions, bool final) +{ + TransactionEngineParams parms = final ? (tepNO_CHECK_FEE | tepUPDATE_TOTAL) : tepNONE; TransactionEngine engine(ledger); for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag())) @@ -657,23 +675,7 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led #endif SerializerIterator sit(item->peekSerializer()); SerializedTransaction::pointer txn = boost::make_shared(boost::ref(sit)); - TransactionEngineResult result = engine.applyTransaction(*txn, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0); - if (result > 0) - { - Log(lsINFO) << " retry"; - assert(!ledger->hasTransaction(item->getTag())); - failedTransactions.push_back(txn); - } - else if (result == 0) - { - Log(lsDEBUG) << " success"; - assert(ledger->hasTransaction(item->getTag())); - } - else - { - Log(lsINFO) << " hard fail"; - assert(!ledger->hasTransaction(item->getTag())); - } + applyTransaction(engine, txn, ledger, failedTransactions, final); #ifndef TRUST_NETWORK } catch (...) @@ -692,8 +694,7 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led { try { - TransactionEngineResult result = - engine.applyTransaction(*it->second, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0); + TransactionEngineResult result = engine.applyTransaction(*it->second, parms, 0); if (result <= 0) { if (result == 0) ++successes; @@ -734,11 +735,12 @@ void LedgerConsensus::accept(SHAMap::pointer set) #endif CanonicalTXSet failedTransactions(set->getHash()); - applyTransactions(set, newLCL, failedTransactions); + applyTransactions(set, newLCL, failedTransactions, true); newLCL->setClosed(); newLCL->setAccepted(); newLCL->updateHash(); uint256 newLCLHash = newLCL->getHash(); + Log(lsTRACE) << "newLCL " << newLCLHash.GetHex(); #ifdef DEBUG if (1) @@ -770,8 +772,29 @@ void LedgerConsensus::accept(SHAMap::pointer set) #endif ScopedLock sl = theApp->getMasterLedger().getLock(); - applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, failedTransactions); - // FIXME: Apply disputed transactions not voted into the candidate set + + // Apply disputed transactions that didn't get in + TransactionEngine engine(newOL); + for (boost::unordered_map::iterator it = mDisputes.begin(), + end = mDisputes.end(); it != end; ++it) + { + if (!it->second->getOurPosition()) + { // we voted NO + try + { + SerializerIterator sit(it->second->peekTransaction()); + SerializedTransaction::pointer txn = boost::make_shared(boost::ref(sit)); + applyTransaction(engine, txn, newOL, failedTransactions, false); + } + catch (...) + { + Log(lsINFO) << "Failed to apply transaction we voted NO on"; + } + } + } + + applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, + failedTransactions, false); theApp->getMasterLedger().pushLedger(newLCL, newOL); mState = lcsACCEPTED; sl.unlock(); diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 721265c245..a02bbce88a 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -13,6 +13,7 @@ #include "LedgerProposal.h" #include "Peer.h" #include "CanonicalTXSet.h" +#include "TransactionEngine.h" class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this { // A transaction set we are trying to acquire @@ -47,7 +48,7 @@ protected: uint256 mTransactionID; int mYays, mNays; bool mOurPosition; - std::vector transaction; + Serializer transaction; boost::unordered_map mVotes; public: @@ -58,7 +59,7 @@ public: const uint256& getTransactionID() const { return mTransactionID; } bool getOurPosition() const { return mOurPosition; } - const std::vector& peekTransaction() { return transaction; } + Serializer& peekTransaction() { return transaction; } void setVote(const uint160& peer, bool votesYes); @@ -115,7 +116,9 @@ protected: void removePosition(LedgerProposal&, bool ours); void sendHaveTxSet(const uint256& set, bool direct); void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger, - CanonicalTXSet& failedTransactions); + CanonicalTXSet& failedTransactions, bool final); + void applyTransaction(TransactionEngine& engine, SerializedTransaction::pointer txn, Ledger::pointer targetLedger, + CanonicalTXSet& failedTransactions, bool final); // manipulating our own position void takeInitialPosition(Ledger::pointer initialLedger); From bca7975c352a2cd0abeb2aa327cf651302a5b2cc Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 18 Jun 2012 13:00:09 -0700 Subject: [PATCH 22/22] We have a bug in doPasswordSet. --- src/LedgerConsensus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index a5ae65551b..4ab170404d 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -638,7 +638,7 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, SerializedTran if (result > 0) { Log(lsINFO) << " retry"; - assert(!ledger->hasTransaction(txn->getTransactionID())); +// assert(!ledger->hasTransaction(txn->getTransactionID())); FIXME: We get these (doPasswordSet) failedTransactions.push_back(txn); } else if (result == 0)