#ifndef __NETWORK_OPS__ #define __NETWORK_OPS__ #include #include #include #include #include "AccountState.h" #include "LedgerMaster.h" #include "NicknameState.h" #include "RippleState.h" #include "SerializedValidation.h" #include "LedgerAcquire.h" #include "LedgerProposal.h" #include "JobQueue.h" #include "AcceptedLedger.h" // Operations that clients may wish to perform against the network // Master operational handler, server sequencer, network tracker class Peer; class LedgerConsensus; DEFINE_INSTANCE(InfoSub); class InfoSub : public IS_INSTANCE(InfoSub) { protected: boost::unordered_set mSubAccountInfo; boost::unordered_set mSubAccountTransaction; boost::mutex mLockInfo; uint64 mSeq; static uint64 sSeq; static boost::mutex sSeqLock; public: typedef boost::shared_ptr pointer; typedef boost::weak_ptr wptr; typedef const boost::shared_ptr& ref; InfoSub() { boost::mutex::scoped_lock sl(sSeqLock); mSeq = ++sSeq; } virtual ~InfoSub(); virtual void send(const Json::Value& jvObj, bool broadcast) = 0; uint64 getSeq() { return mSeq; } void onSendEmpty(); void insertSubAccountInfo(RippleAddress addr, uint32 uLedgerIndex) { boost::mutex::scoped_lock sl(mLockInfo); mSubAccountInfo.insert(addr); } }; class NetworkOPs { public: enum Fault { // exceptions these functions can throw IO_ERROR = 1, NO_NETWORK = 2, }; enum OperatingMode { // how we process transactions or account balance requests omDISCONNECTED = 0, // not ready to process requests omCONNECTED = 1, // convinced we are talking to the network omTRACKING = 2, // convinced we agree with the network omFULL = 3 // we have the ledger and can even validate }; typedef boost::unordered_map subMapType; protected: typedef boost::unordered_map subInfoMapType; typedef boost::unordered_map::value_type subInfoMapValue; typedef boost::unordered_map::iterator subInfoMapIterator; typedef boost::unordered_map subRpcMapType; OperatingMode mMode; bool mNeedNetworkLedger; bool mProposing, mValidating; boost::posix_time::ptime mConnectTime; boost::asio::deadline_timer mNetTimer; boost::shared_ptr mConsensus; boost::unordered_map > mStoredProposals; LedgerMaster* mLedgerMaster; LedgerAcquire::pointer mAcquiringLedger; int mCloseTimeOffset; // last ledger close int mLastCloseProposers, mLastCloseConvergeTime; uint256 mLastCloseHash; uint32 mLastCloseTime; uint32 mLastValidationTime; SerializedValidation::pointer mLastValidation; // Recent positions taken std::map > mRecentPositions; // XXX Split into more locks. boost::recursive_mutex mMonitorLock; subInfoMapType mSubAccount; subInfoMapType mSubRTAccount; subRpcMapType mRpcSubMap; subMapType mSubLedger; // accepted ledgers subMapType mSubServer; // when server changes connectivity state subMapType mSubTransactions; // all accepted transactions subMapType mSubRTTransactions; // all proposed and accepted transactions TaggedCache< uint256, std::vector > mFetchPack; uint32 mLastFetchPack; uint32 mLastLoadBase; uint32 mLastLoadFactor; void setMode(OperatingMode); Json::Value transJson(const SerializedTransaction& stTxn, TER terResult, bool bValidated, Ledger::ref lpCurrent); bool haveConsensusObject(); Json::Value pubBootstrapAccountInfo(Ledger::ref lpAccepted, const RippleAddress& naAccountID); void pubValidatedTransaction(Ledger::ref alAccepted, const ALTransaction& alTransaction); void pubAccountTransaction(Ledger::ref lpCurrent, const ALTransaction& alTransaction, bool isAccepted); void pubServer(); public: NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedgerMaster); // network information uint32 getNetworkTimeNC(); // Our best estimate of wall time in seconds from 1/1/2000 uint32 getCloseTimeNC(); // Our best estimate of current ledger close time uint32 getValidationTimeNC(); // Use *only* to timestamp our own validation void closeTimeOffset(int); boost::posix_time::ptime getNetworkTimePT(); uint32 getLedgerID(const uint256& hash); uint32 getCurrentLedgerID(); OperatingMode getOperatingMode() { return mMode; } std::string strOperatingMode(); Ledger::ref getClosedLedger() { return mLedgerMaster->getClosedLedger(); } Ledger::ref getValidatedLedger() { return mLedgerMaster->getValidatedLedger(); } Ledger::ref getCurrentLedger() { return mLedgerMaster->getCurrentLedger(); } Ledger::pointer getLedgerByHash(const uint256& hash) { return mLedgerMaster->getLedgerByHash(hash); } Ledger::pointer getLedgerBySeq(const uint32 seq); uint256 getClosedLedgerHash() { return mLedgerMaster->getClosedLedger()->getHash(); } // Do we have this inclusive range of ledgers in our database bool haveLedgerRange(uint32 from, uint32 to); bool haveLedger(uint32 seq); uint32 getValidatedSeq(); bool isValidated(uint32 seq); bool isValidated(uint32 seq, const uint256& hash); bool isValidated(Ledger::ref l) { return isValidated(l->getLedgerSeq(), l->getHash()); } bool getValidatedRange(uint32& minVal, uint32& maxVal) { return mLedgerMaster->getValidatedRange(minVal, maxVal); } SerializedValidation::ref getLastValidation() { return mLastValidation; } void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; } SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); } SLE::pointer getSLEi(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLEi(uHash); } // // Transaction operations // typedef FUNCTION_TYPE stCallback; // must complete immediately void submitTransaction(Job&, SerializedTransaction::pointer, stCallback callback = stCallback()); Transaction::pointer submitTransactionSync(Transaction::ref tpTrans, bool bAdmin, bool bSubmit); void runTransactionQueue(); Transaction::pointer processTransaction(Transaction::pointer, bool bAdmin, stCallback); Transaction::pointer processTransaction(Transaction::pointer transaction, bool bAdmin) { return processTransaction(transaction, bAdmin, stCallback()); } Transaction::pointer findTransactionByID(const uint256& transactionID); #if 0 int findTransactionsBySource(const uint256& uLedger, std::list&, const RippleAddress& sourceAccount, uint32 minSeq, uint32 maxSeq); #endif int findTransactionsByDestination(std::list&, const RippleAddress& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions); // // Account functions // AccountState::pointer getAccountState(Ledger::ref lrLedger, const RippleAddress& accountID); SLE::pointer getGenerator(Ledger::ref lrLedger, const uint160& uGeneratorID); // // Directory functions // STVector256 getDirNodeInfo(Ledger::ref lrLedger, const uint256& uRootIndex, uint64& uNodePrevious, uint64& uNodeNext); #if 0 // // Nickname functions // NicknameState::pointer getNicknameState(const uint256& uLedger, const std::string& strNickname); #endif // // Owner functions // Json::Value getOwnerInfo(Ledger::pointer lpLedger, const RippleAddress& naAccount); // // Book functions // void getBookPage(Ledger::pointer lpLedger, const uint160& uTakerPaysCurrencyID, const uint160& uTakerPaysIssuerID, const uint160& uTakerGetsCurrencyID, const uint160& uTakerGetsIssuerID, const uint160& uTakerID, const bool bProof, const unsigned int iLimit, const Json::Value& jvMarker, Json::Value& jvResult); // raw object operations bool findRawLedger(const uint256& ledgerHash, std::vector& rawLedger); bool findRawTransaction(const uint256& transactionHash, std::vector& rawTransaction); bool findAccountNode(const uint256& nodeHash, std::vector& rawAccountNode); bool findTransactionNode(const uint256& nodeHash, std::vector& rawTransactionNode); // tree synchronization operations bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID, const std::vector& myNode, std::list< std::vector >& newNodes); bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId, const std::vector& myNode, std::list< std::vector >& newNodes); // ledger proposal/close functions void processTrustedProposal(LedgerProposal::pointer proposal, boost::shared_ptr set, RippleAddress nodePublic, uint256 checkLedger, bool sigGood); SMAddNode gotTXData(const boost::shared_ptr& peer, const uint256& hash, const std::list& nodeIDs, const std::list< std::vector >& nodeData); bool recvValidation(SerializedValidation::ref val, const std::string& source); void takePosition(int seq, SHAMap::ref position); SHAMap::pointer getTXMap(const uint256& hash); bool hasTXSet(const boost::shared_ptr& peer, const uint256& set, ripple::TxSetStatus status); void mapComplete(const uint256& hash, SHAMap::ref map); bool stillNeedTXSet(const uint256& hash); void makeFetchPack(Job&, boost::weak_ptr peer, boost::shared_ptr request, Ledger::pointer wantLedger, Ledger::pointer haveLedger); bool shouldFetchPack(); void gotFetchPack(bool progress); void addFetchPack(const uint256& hash, boost::shared_ptr< std::vector >& data); bool getFetchPack(const uint256& hash, std::vector& data); int getFetchSize(); void sweepFetchPack(); // network state machine void checkState(const boost::system::error_code& result); void switchLastClosedLedger(Ledger::pointer newLedger, bool duringConsensus); // Used for the "jump" case bool checkLastClosedLedger(const std::vector&, uint256& networkClosed); int beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger); void tryStartConsensus(); void endConsensus(bool correctLCL); void setStandAlone() { setMode(omFULL); } void setStateTimer(); void newLCL(int proposers, int convergeTime, const uint256& ledgerHash); void needNetworkLedger() { mNeedNetworkLedger = true; } void clearNeedNetworkLedger() { mNeedNetworkLedger = false; } bool isNeedNetworkLedger() { return mNeedNetworkLedger; } bool isFull() { return !mNeedNetworkLedger && (mMode == omFULL); } void setProposing(bool p, bool v) { mProposing = p; mValidating = v; } bool isProposing() { return mProposing; } bool isValidating() { return mValidating; } void consensusViewChange(); int getPreviousProposers() { return mLastCloseProposers; } int getPreviousConvergeTime() { return mLastCloseConvergeTime; } uint32 getLastCloseTime() { return mLastCloseTime; } void setLastCloseTime(uint32 t) { mLastCloseTime = t; } Json::Value getConsensusInfo(); Json::Value getServerInfo(bool human, bool admin); uint32 acceptLedger(); boost::unordered_map >& peekStoredProposals() { return mStoredProposals; } void storeProposal(LedgerProposal::ref proposal, const RippleAddress& peerPublic); uint256 getConsensusLCL(); void reportFeeChange(); //Helper function to generate SQL query to get transactions std::string transactionsSQL(std::string selection, const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, int limit, bool binary, bool count, bool bAdmin); // client information retrieval functions std::vector< std::pair > getAccountTxs(const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, int limit, bool bAdmin); typedef boost::tuple txnMetaLedgerType; std::vector getAccountTxsB(const RippleAddress& account, int32 minLedger, int32 maxLedger, bool descending, uint32 offset, int limit, bool bAdmin); std::vector getLedgerAffectedAccounts(uint32 ledgerSeq); std::vector getLedgerTransactions(uint32 ledgerSeq); uint32 countAccountTxs(const RippleAddress& account, int32 minLedger, int32 maxLedger); // // Monitoring: publisher side // void pubLedger(Ledger::ref lpAccepted); void pubProposedTransaction(Ledger::ref lpCurrent, SerializedTransaction::ref stTxn, TER terResult); // // Monitoring: subscriber side // void subAccount(InfoSub::ref ispListener, const boost::unordered_set& vnaAccountIDs, uint32 uLedgerIndex, bool rt); void unsubAccount(uint64 uListener, const boost::unordered_set& vnaAccountIDs, bool rt); bool subLedger(InfoSub::ref ispListener, Json::Value& jvResult); bool unsubLedger(uint64 uListener); bool subServer(InfoSub::ref ispListener, Json::Value& jvResult); bool unsubServer(uint64 uListener); bool subBook(InfoSub::ref ispListener, const uint160& currencyPays, const uint160& currencyGets, const uint160& issuerPays, const uint160& issuerGets); bool unsubBook(uint64 uListener, const uint160& currencyPays, const uint160& currencyGets, const uint160& issuerPays, const uint160& issuerGets); bool subTransactions(InfoSub::ref ispListener); bool unsubTransactions(uint64 uListener); bool subRTTransactions(InfoSub::ref ispListener); bool unsubRTTransactions(uint64 uListener); InfoSub::pointer findRpcSub(const std::string& strUrl); InfoSub::pointer addRpcSub(const std::string& strUrl, InfoSub::ref rspEntry); }; #endif // vim:ts=4