#include "LedgerConsensus.h" TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mHaveRoot(false) { mMap = boost::make_shared(); mMap->setSynching(); } void TransactionAcquire::done() { // insert SHAMap in finished set (as valid or invalid), remove ourselves from current set // WRITEME } boost::weak_ptr TransactionAcquire::pmDowncast() { return boost::shared_polymorphic_downcast(shared_from_this()); } void TransactionAcquire::trigger(Peer::pointer peer) { if (mComplete || mFailed) return; if (!mHaveRoot) { boost::shared_ptr tmGL = boost::make_shared(); tmGL->set_ledgerhash(mHash.begin(), mHash.size()); tmGL->set_itype(newcoin::liTS_CANDIDATE); *(tmGL->add_nodeids()) = SHAMapNode().getRawString(); sendRequest(tmGL, peer); } if (mHaveRoot) { std::vector nodeIDs; std::vector nodeHashes; mMap->getMissingNodes(nodeIDs, nodeHashes, 256); if (nodeIDs.empty()) { if (mMap->isValid()) mComplete = true; else mFailed = true; } else { boost::shared_ptr tmGL = boost::make_shared(); tmGL->set_ledgerhash(mHash.begin(), mHash.size()); tmGL->set_itype(newcoin::liTS_CANDIDATE); for (std::vector::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it) *(tmGL->add_nodeids()) = it->getRawString(); if (peer) sendRequest(tmGL, peer); else sendRequest(tmGL); return; } } if (mComplete || mFailed) done(); else resetTimer(); } bool TransactionAcquire::takeNodes(const std::list& nodeIDs, const std::list< std::vector >& data, Peer::pointer peer) { if (mComplete) return true; if (mFailed) return false; std::list::const_iterator nodeIDit = nodeIDs.begin(); std::list< std::vector >::const_iterator nodeDatait = data.begin(); while (nodeIDit != nodeIDs.end()) { if (nodeIDit->isRoot()) { if (!mMap->addRootNode(getHash(), *nodeDatait)) return false; } else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait)) return false; ++nodeIDit; ++nodeDatait; } trigger(peer); return true; } LedgerConsensus::LedgerConsensus(Ledger::pointer previousLedger) : mState(lcsPRE_CLOSE), mPreviousLedger(previousLedger) { } void LedgerConsensus::closeTime(Ledger::pointer& current) { if (mState != lcsPRE_CLOSE) { assert(false); return; } CKey::pointer nodePrivKey = boost::make_shared(); nodePrivKey->MakeNewKey(); // FIXME current->updateHash(); uint256 txSet = current->getTransHash(); mOurPosition = boost::make_shared(nodePrivKey, current->getParentHash(), txSet); mComplete[txSet] = current->peekTransactionMap()->snapShot(); // WRITME: Broadcast an IHAVE for this set } void LedgerConsensus::abort() { } int LedgerConsensus::startup() { return 1; } int LedgerConsensus::timerEntry() { return 1; } SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire) { boost::unordered_map::iterator it = mComplete.find(hash); if (it == mComplete.end()) { // we have not completed acuiqiring this ledger if (doAcquire) { TransactionAcquire::pointer& acquiring = mAcquiring[hash]; if (!acquiring) { acquiring = boost::make_shared(hash); startAcquiring(acquiring); } } return SHAMap::pointer(); } return it->second; } void LedgerConsensus::startAcquiring(TransactionAcquire::pointer acquire) { boost::unordered_map< uint256, std::vector< boost::weak_ptr > >::iterator it = mPeerData.find(acquire->getHash()); if (it != mPeerData.end()) { // Add any peers we already know have his transaction set std::vector< boost::weak_ptr >& peerList = it->second; std::vector< boost::weak_ptr >::iterator pit = peerList.begin(); while (pit != peerList.end()) { Peer::pointer pr = pit->lock(); if (!pr) pit = peerList.erase(pit); else { acquire->peerHas(pr); ++pit; } } } } void LedgerConsensus::removePosition(LedgerProposal& position) { // WRITEME } void LedgerConsensus::addPosition(LedgerProposal& position) { // WRITEME } bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition) { LedgerProposal::pointer& currentPosition = mPeerPositions[newPosition->getPeerID()]; if (!currentPosition) { if (newPosition->getProposeSeq() <= currentPosition->getProposeSeq()) return false; // change in position removePosition(*currentPosition); } currentPosition = newPosition; addPosition(*currentPosition); return true; } bool LedgerConsensus::peerHasSet(Peer::pointer peer, const std::vector& sets) { for (std::vector::const_iterator it = sets.begin(), end = sets.end(); it != end; ++it) { std::vector< boost::weak_ptr >& set = mPeerData[*it]; bool found = false; for (std::vector< boost::weak_ptr >::iterator iit = set.begin(), iend = set.end(); iit != iend; ++iit) if (iit->lock() == peer) found = true; if (!found) { set.push_back(peer); boost::unordered_map::iterator acq = mAcquiring.find(*it); if (acq != mAcquiring.end()) acq->second->peerHas(peer); } } return true; } bool LedgerConsensus::peerGaveNodes(Peer::pointer peer, const uint256& setHash, const std::list& nodeIDs, const std::list< std::vector >& nodeData) { boost::unordered_map::iterator acq = mAcquiring.find(setHash); if (acq == mAcquiring.end()) return false; return acq->second->takeNodes(nodeIDs, nodeData, peer); }