From 24d7ca9ebc6bfdf94ba14b75dde2f2dd6015b8c8 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Jul 2015 14:37:06 +0200 Subject: [PATCH] TransactionQueue docs --- libethereum/TransactionQueue.cpp | 21 +++++------ libethereum/TransactionQueue.h | 61 ++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 36d337e7b..2554544a3 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -36,12 +36,12 @@ TransactionQueue::TransactionQueue(unsigned _limit, unsigned _futureLimit): m_limit(_limit), m_futureLimit(_futureLimit) { - unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; - for (unsigned i = 0; i < verifierThreads; ++i) - m_verifiers.emplace_back([=](){ - setThreadName("txcheck" + toString(i)); - this->verifierBody(); - }); + unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; + for (unsigned i = 0; i < verifierThreads; ++i) + m_verifiers.emplace_back([=](){ + setThreadName("txcheck" + toString(i)); + this->verifierBody(); + }); } TransactionQueue::~TransactionQueue() @@ -68,6 +68,9 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, IfDropped _ try { + // Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender. + // If it doesn't work, the signature is bad. + // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). t = Transaction(_transactionRLP, CheckTransaction::Everything); UpgradeGuard ul(l); ir = manageImport_WITH_LOCK(h, t); @@ -99,7 +102,6 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, IfDropped ImportResult ret; { UpgradableGuard l(m_lock); - // TODO: keep old transactions around and check in State for nonce validity auto ir = check_WITH_LOCK(h, _ik); if (ir != ImportResult::Success) return ir; @@ -132,11 +134,7 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio { try { - // Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender. - // If it doesn't work, the signature is bad. - // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). assert(_h == _transaction.sha3()); - // Remove any prior transaction with the same nonce but a lower gas price. // Bomb out if there's a prior transaction with higher gas price. auto cs = m_currentByAddressAndNonce.find(_transaction.from()); @@ -263,7 +261,6 @@ unsigned TransactionQueue::waiting(Address const& _a) const void TransactionQueue::setFuture(h256 const& _txHash) { -// cdebug << "txQ::setFuture" << _t.first; WriteGuard l(m_lock); auto it = m_currentByHash.find(_txHash); if (it == m_currentByHash.end()) diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index ad8bd4a87..f6c140e6f 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -42,39 +42,84 @@ struct TransactionQueueChannel: public LogChannel { static const char* name(); s struct TransactionQueueTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 7; }; #define ctxq dev::LogOutputStream() -enum class IfDropped { Ignore, Retry }; +/// Import transaction policy +enum class IfDropped +{ + Ignore, ///< Don't import transaction that was previously dropped. + Retry ///< Import transaction even if it was dropped before. +}; /** * @brief A queue of Transactions, each stored as RLP. - * Maintains a transaction queue sorted by nonce diff and gas price + * Maintains a transaction queue sorted by nonce diff and gas price. * @threadsafe */ class TransactionQueue { public: /// @brief TransactionQueue - /// @param _limit Maximum number of pending transactions in the queue - /// @param _futureLimit Maximum number of future nonce transactions + /// @param _limit Maximum number of pending transactions in the queue. + /// @param _futureLimit Maximum number of future nonce transactions. TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024); ~TransactionQueue(); + /// Add transaction to the queue to be verified and imported. + /// @param _data RLP encoded transaction data. + /// @param _nodeId Optional network identified of a node transaction comes from. void enqueue(RLP const& _data, h512 const& _nodeId); + + /// Verify and add transaction to the queue synchronously. + /// @param _tx RLP encoded transaction data. + /// @param _ik Set to Retry to force re-addinga transaction that was previously dropped. + /// @returns Import result code. ImportResult import(bytes const& _tx, IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _ik); } + + /// Verify and add transaction to the queue synchronously. + /// @param _tx Trasnaction data. + /// @param _ik Set to Retry to force re-addinga transaction that was previously dropped. + /// @returns Import result code. ImportResult import(Transaction const& _tx, IfDropped _ik = IfDropped::Ignore); + /// Remove transaction from the queue + /// @param _txHash Trasnaction hash void drop(h256 const& _txHash); + /// Get number of pending transactions for account. + /// @returns Pending transaction count. unsigned waiting(Address const& _a) const; + + /// Get top transactions from the queue. Returned transactions are not removed from the queue automatically. + /// @param _limit Max number of transactions to return. + /// @returns up to _limit transactions ordered by nonce and gas price. Transactions topTransactions(unsigned _limit) const; + + /// Get a hash set of transactions in the queue + /// @returns A hash set of all transactions in the queue h256Hash knownTransactions() const; + + /// Get max nonce for an account + /// @returns Max transaction nonce for account in the queue u256 maxNonce(Address const& _a) const; + + /// Mark transaction as future. It wont be retured in topTransactions list until a transaction with a preceeding nonce is imported or marked with dropGood + /// @param _t Transaction hash void setFuture(h256 const& _t); + + /// Drop a trasnaction from the list if exists and move following future trasnactions to current (if any) + /// @param _t Transaction hash void dropGood(Transaction const& _t); + /// Clear the queue void clear(); + + /// Register a handler that will be called once there is a new transaction imported template Handler<> onReady(T const& _t) { return m_onReady.add(_t); } + + /// Register a handler that will be called once asynchronous verification is comeplte an transaction has been imported template Handler onImport(T const& _t) { return m_onImport.add(_t); } private: + + /// Verified and imported transaction struct VerifiedTransaction { VerifiedTransaction(Transaction const& _t): transaction(_t) {} @@ -83,9 +128,10 @@ private: VerifiedTransaction(VerifiedTransaction const&) = delete; VerifiedTransaction& operator=(VerifiedTransaction const&) = delete; - Transaction transaction; + Transaction transaction; ///< Transaction data }; + /// Trasnaction pending verification struct UnverifiedTransaction { UnverifiedTransaction() {} @@ -96,13 +142,14 @@ private: UnverifiedTransaction(UnverifiedTransaction const&) = delete; UnverifiedTransaction& operator=(UnverifiedTransaction const&) = delete; - bytes transaction; - h512 nodeId; + bytes transaction; ///< RLP encoded transaction data + h512 nodeId; ///< Network Id of the peer transaction comes from }; struct PriorityCompare { TransactionQueue& queue; + /// Compare transaction by nonce height and gas price. bool operator()(VerifiedTransaction const& _first, VerifiedTransaction const& _second) const { u256 const& height1 = _first.transaction.nonce() - queue.m_currentByAddressAndNonce[_first.transaction.sender()].begin()->first;