#ifndef __LEDGER_CONSENSUS__ #define __LEDGER_CONSENSUS__ #include #include #include #include #include #include "key.h" #include "Transaction.h" #include "LedgerAcquire.h" #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 public: typedef boost::shared_ptr pointer; protected: SHAMap::pointer mMap; bool mHaveRoot; void onTimer() { trigger(Peer::pointer()); } void newPeer(Peer::pointer peer) { trigger(peer); } void done(); void trigger(Peer::pointer); boost::weak_ptr pmDowncast(); public: TransactionAcquire(const uint256& hash); SHAMap::pointer getMap() { return mMap; } bool takeNodes(const std::list& IDs, const std::list< std::vector >& data, Peer::pointer); }; class LCTransaction { // A transaction that may be disputed protected: uint256 mTransactionID; int mYays, mNays; bool mOurPosition; Serializer transaction; boost::unordered_map mVotes; public: typedef boost::shared_ptr pointer; 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; } Serializer& peekTransaction() { return transaction; } void setVote(const uint160& peer, bool votesYes); bool updatePosition(int percentTime, bool proposing); }; enum LCState { lcsPRE_CLOSE, // We haven't closed our ledger yet, but others might have lcsESTABLISH, // Establishing consensus lcsFINISHED, // We have closed on a transaction set lcsACCEPTED, // We have accepted/validated a new last closed ledger lcsABORTED // Abandoned }; class LedgerConsensus : public boost::enable_shared_from_this { protected: LCState mState; uint32 mCloseTime; // The wall time this ledger closed uint256 mPrevLedgerHash, mNewLedgerHash; Ledger::pointer mPreviousLedger; LedgerAcquire::pointer mAcquiringLedger; LedgerProposal::pointer mOurPosition; NewcoinAddress mValSeed; bool mProposing, mValidating, mHaveCorrectLCL; int mCurrentSeconds, mClosePercent, mCloseResolution; bool mHaveCloseTimeConsensus; boost::posix_time::ptime mConsensusStartTime; int mPreviousProposers; int mPreviousSeconds; // Convergence tracking, trusted peers indexed by hash of public key boost::unordered_map mPeerPositions; // Transaction Sets, indexed by hash of transaction tree boost::unordered_map mComplete; boost::unordered_map mAcquiring; // Peer sets boost::unordered_map > > mPeerData; // Disputed transactions boost::unordered_map mDisputes; // Close time estimates std::map mCloseTimes; // final accept logic static void Saccept(boost::shared_ptr This, SHAMap::pointer txSet); void accept(SHAMap::pointer txSet); void weHave(const uint256& id, Peer::pointer avoidPeer); 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); void addPosition(LedgerProposal&, bool ours); void removePosition(LedgerProposal&, bool ours); void sendHaveTxSet(const uint256& set, bool direct); void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger, CanonicalTXSet& failedTransactions, bool final); void applyTransaction(TransactionEngine& engine, SerializedTransaction::pointer txn, Ledger::pointer targetLedger, CanonicalTXSet& failedTransactions, bool final); // manipulating our own position void statusChange(newcoin::NodeEvent, Ledger::pointer ledger); void takeInitialPosition(Ledger::pointer initialLedger); void updateOurPositions(); int getThreshold(); void beginAccept(); void endConsensus(); public: LedgerConsensus(const uint256& prevLCLHash, Ledger::pointer previousLedger, uint32 closeTime); int startup(); Ledger::pointer peekPreviousLedger() { return mPreviousLedger; } uint256 getLCL() { return mPrevLedgerHash; } SHAMap::pointer getTransactionTree(const uint256& hash, bool doAcquire); TransactionAcquire::pointer getAcquiring(const uint256& hash); void mapComplete(const uint256& hash, SHAMap::pointer map, bool acquired); void abort(); void timerEntry(); // state handlers int statePreClose(); int stateEstablish(); int stateCutoff(); int stateFinished(); int stateAccepted(); bool haveConsensus(); bool peerPosition(LedgerProposal::pointer); bool peerHasSet(Peer::pointer peer, const uint256& set, newcoin::TxSetStatus status); bool peerGaveNodes(Peer::pointer peer, const uint256& setHash, const std::list& nodeIDs, const std::list< std::vector >& nodeData); }; #endif