From 7e38de27108f231639a80cfa069c3d99e992f023 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 3 Mar 2014 12:21:23 +0000 Subject: [PATCH] Avoid reprocessing future transactions until it's possible they're valid. --- libethereum/PeerNetwork.cpp | 5 ++-- libethereum/State.cpp | 44 ++++++++++++++++++++------------ libethereum/TransactionQueue.cpp | 17 ++++++++++++ libethereum/TransactionQueue.h | 6 ++++- 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/libethereum/PeerNetwork.cpp b/libethereum/PeerNetwork.cpp index c77af38eb..c7d699461 100644 --- a/libethereum/PeerNetwork.cpp +++ b/libethereum/PeerNetwork.cpp @@ -830,9 +830,8 @@ void PeerServer::ensureAccepting() { clog(NetWarn) << "ERROR: " << _e.what(); } - m_accepting = false; - if (m_mode == NodeMode::PeerServer || m_peers.size() < m_idealPeerCount * 2) + if (ec.value() != 1 && m_mode == NodeMode::PeerServer || m_peers.size() < m_idealPeerCount * 2) ensureAccepting(); }); } @@ -926,7 +925,7 @@ bool PeerServer::sync(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o) { for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it) if (_tq.import(*it)) - ret = true; + {}//ret = true; // just putting a transaction in the queue isn't enough to change the state - it might have an invalid nonce... else m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on. m_incomingTransactions.clear(); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 74db7aeb4..f14c8c18c 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -288,31 +288,41 @@ bool State::sync(TransactionQueue& _tq) // TRANSACTIONS bool ret = false; auto ts = _tq.transactions(); - for (auto const& i: ts) + vector> futures; + + for (int goodTxs = 1; goodTxs;) { - if (!m_transactionSet.count(i.first)) + goodTxs = 0; + for (auto const& i: ts) { - // don't have it yet! Execute it now. - try + if (!m_transactionSet.count(i.first)) { - execute(i.second); - ret = true; - } - catch (InvalidNonce const& in) - { - if (in.required > in.candidate) + // don't have it yet! Execute it now. + try + { + execute(i.second); + ret = true; + _tq.noteGood(i); + ++goodTxs; + } + catch (InvalidNonce const& in) + { + if (in.required > in.candidate) + { + // too old + _tq.drop(i.first); + ret = true; + } + else + _tq.setFuture(i); + } + catch (std::exception const&) { - // too old + // Something else went wrong - drop it. _tq.drop(i.first); ret = true; } } - catch (std::exception const&) - { - // Something else went wrong - drop it. - _tq.drop(i.first); - ret = true; - } } } return ret; diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 2b908d8b2..1c6144eab 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -51,3 +51,20 @@ bool TransactionQueue::import(bytes const& _block) return true; } + +void TransactionQueue::setFuture(std::pair const& _t) +{ + if (m_data.count(_t.first)) + { + m_data.erase(_t.first); + m_future.insert(make_pair(Transaction(_t.second).sender(), _t)); + } +} + +void TransactionQueue::noteGood(std::pair const& _t) +{ + auto r = m_future.equal_range(Transaction(_t.second).sender()); + for (auto it = r.first; it != r.second; ++it) + m_data.insert(_t); + m_future.erase(r.first); +} diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 8f2ccaef1..89e889cc1 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -40,14 +40,18 @@ public: void drop(h256 _txHash) { m_data.erase(_txHash); } std::map const& transactions() const { return m_data; } + void setFuture(std::pair const& _t); + void noteGood(std::pair const& _t); + Transactions interestQueue() { Transactions ret; swap(ret, m_interestQueue); return ret; } void pushInterest(Address _a) { m_interest[_a]++; } void popInterest(Address _a) { if (m_interest[_a] > 1) m_interest[_a]--; else if (m_interest[_a]) m_interest.erase(_a); } private: - std::map m_data; ///< the queue. + std::map m_data; ///< Map of SHA3(tx) to tx. Transactions m_interestQueue; std::map m_interest; + std::multimap> m_future; ///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX. }; }