From 7e8ebcc3d91ace12643260e4f2d10f24f71509cf Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 28 May 2012 01:31:35 -0700 Subject: [PATCH] Consensus timing and avalanche. Transaction position change. Track transaction data for all disputed transactions. Update our set as our 'vote' changes. --- src/LedgerConsensus.cpp | 71 +++++++++++++++++++++++++++++++++++++---- src/LedgerConsensus.h | 15 +++++---- src/LedgerTiming.h | 4 +++ src/NetworkOPs.cpp | 3 +- 4 files changed, 80 insertions(+), 13 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index a616e6b286..d7cb4b5863 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -3,6 +3,7 @@ #include "Application.h" #include "NetworkOPs.h" +#include "LedgerTiming.h" TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mHaveRoot(false) { @@ -118,8 +119,26 @@ void LCTransaction::setVote(const uint256& peer, bool votesYes) } } -LedgerConsensus::LedgerConsensus(Ledger::pointer previousLedger) - : mState(lcsPRE_CLOSE), mPreviousLedger(previousLedger) +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; + + int weight = (mYays * 100 + (mOurPosition ? 100 : 0)) / (mNays + mYays + 1); + + bool newPosition; + if (seconds <= LEDGER_CONVERGE) newPosition = weight >= MIN_CONSENSUS; + else if (seconds >= LEDGER_FORCE_CONVERGE) newPosition = weight >= MAX_CONSENSUS; + else newPosition = weight >= AVG_CONSENSUS; + + if (newPosition == mOurPosition) return false; + mOurPosition = newPosition; + return true; +} + +LedgerConsensus::LedgerConsensus(Ledger::pointer previousLedger, uint32 closeTime) + : mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPreviousLedger(previousLedger) { } @@ -130,6 +149,7 @@ void LedgerConsensus::closeTime(Ledger::pointer& current) assert(false); return; } + CKey::pointer nodePrivKey = boost::make_shared(); nodePrivKey->MakeNewKey(); // FIXME @@ -160,8 +180,12 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map) SHAMap::SHAMapDiff differences; it2->second->compare(it->second, differences, 16384); for(SHAMap::SHAMapDiff::iterator pos = differences.begin(), end = differences.end(); pos != end; ++pos) - { // create disputed transactions - addDisputedTransaction(pos->first); + { // create disputed transactions (from the ledger that has them) + if (pos->second.first) + addDisputedTransaction(pos->first, pos->second.first->peekData()); + else if(pos->second.second) + addDisputedTransaction(pos->first, pos->second.second->peekData()); + else assert(false); } } } @@ -204,6 +228,41 @@ int LedgerConsensus::startup() int LedgerConsensus::timerEntry() { + int sinceClose = theApp->getOPs().getNetworkTimeNC() - mCloseTime; + if ((mState == lcsESTABLISH) || (mState == lcsCUTOFF)) + { + if (sinceClose >= LEDGER_FORCE_CONVERGE) + { + mState = lcsCUTOFF; + sinceClose = LEDGER_FORCE_CONVERGE; + } + + bool changes = false; + SHAMap::pointer ourPosition; + + for(boost::unordered_map::iterator it = mDisputes.begin(), + end = mDisputes.end(); it != end; ++it) + { + if (it->second->updatePosition(sinceClose)) + { + if (changes) + { + ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(); + changes = true; + } + if (it->second->getOurPosition()) // now a yes + ourPosition->addItem(SHAMapItem(it->first, it->second->peekTransaction()), true); + else // now a no + ourPosition->delItem(it->first); + } + } + + if (changes) + { + // broadcast IHAVE + // broadcast new proposal + } + } return 1; } @@ -249,7 +308,7 @@ void LedgerConsensus::startAcquiring(TransactionAcquire::pointer acquire) } } -void LedgerConsensus::addDisputedTransaction(const uint256& txID) +void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vector& tx) { boost::unordered_map::iterator it = mDisputes.find(txID); if (it != mDisputes.end()) return; @@ -263,7 +322,7 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID) else assert(false); // We don't have our own position? } - LCTransaction::pointer txn = boost::make_shared(txID, ourPosition); + LCTransaction::pointer txn = boost::make_shared(txID, tx, ourPosition); mDisputes[txID] = txn; for (boost::unordered_map::iterator pit = mPeerPositions.begin(), diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index af46afe4f8..2de63dd695 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -44,16 +44,18 @@ protected: uint256 mTransactionID; int mYays, mNays; bool mOurPosition; + std::vector transaction; boost::unordered_map mVotes; public: typedef boost::shared_ptr pointer; - LCTransaction(const uint256 &txID, bool ourPosition) : mTransactionID(txID), mYays(0), mNays(0), - mOurPosition(ourPosition) { ; } + LCTransaction(const uint256 &txID, const std::vector& tx, bool ourPosition) : + mTransactionID(txID), mYays(0), mNays(0), mOurPosition(ourPosition), transaction(tx) { ; } - const uint256& getTransactionID() const { return mTransactionID; } - bool getOurPosition() const { return mOurPosition; } + const uint256& getTransactionID() const { return mTransactionID; } + bool getOurPosition() const { return mOurPosition; } + const std::vector& peekTransaction() { return transaction; } void setVote(const uint256& peer, bool votesYes); @@ -74,6 +76,7 @@ class LedgerConsensus { protected: LCState mState; + uint32 mCloseTime; Ledger::pointer mPreviousLedger; LedgerProposal::pointer mOurPosition; @@ -94,7 +97,7 @@ protected: void startAcquiring(TransactionAcquire::pointer); SHAMap::pointer find(const uint256& hash); - void addDisputedTransaction(const uint256&); + void addDisputedTransaction(const uint256&, const std::vector& transaction); void adjustCount(SHAMap::pointer map, const std::vector& peers); void addPosition(LedgerProposal&, bool ours); @@ -102,7 +105,7 @@ protected: int getThreshold(); public: - LedgerConsensus(Ledger::pointer previousLedger); + LedgerConsensus(Ledger::pointer previousLedger, uint32 closeTime); void closeTime(Ledger::pointer& currentLedger); int startup(); diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index 3221122bb1..1e64ccc651 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -30,4 +30,8 @@ #endif +#define MIN_CONSENSUS 50 +#define AVG_CONSENSUS 60 +#define MAX_CONSENSUS 70 + #endif diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 2f7fe62a0e..f5001c1b19 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -368,7 +368,8 @@ int NetworkOPs::beginConsensus(Ledger::pointer closingLedger, bool isEarly) // Create a consensus object to get consensus on this ledger if (!!mConsensus) mConsensus->abort(); - mConsensus = boost::make_shared(prevLedger); + mConsensus = boost::make_shared(prevLedger, + theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC()); mConsensus->closeTime(closingLedger); // FIXME: Create consensus a few seconds before close time #ifdef DEBUG