Ethereum  PoC-8
The C++ Implementation of Ethereum
TransactionQueue.h
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #pragma once
23 
24 #include <functional>
25 #include <condition_variable>
26 #include <thread>
27 #include <deque>
28 #include <libdevcore/Common.h>
29 #include <libdevcore/Guards.h>
30 #include <libdevcore/Log.h>
31 #include <libethcore/Common.h>
32 #include "Transaction.h"
33 
34 namespace dev
35 {
36 namespace eth
37 {
38 
45 {
46 public:
47  struct Limits { size_t current; size_t future; };
48 
52  TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024);
53  TransactionQueue(Limits const& _l): TransactionQueue(_l.current, _l.future) {}
58  void enqueue(RLP const& _data, h512 const& _nodeId);
59 
64  ImportResult import(bytes const& _tx, IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _ik); }
65 
70  ImportResult import(Transaction const& _tx, IfDropped _ik = IfDropped::Ignore);
71 
74  void drop(h256 const& _txHash);
75 
78  unsigned waiting(Address const& _a) const;
79 
84  Transactions topTransactions(unsigned _limit, h256Hash const& _avoid = h256Hash()) const;
85 
89 
92  u256 maxNonce(Address const& _a) const;
93 
96  void setFuture(h256 const& _t);
97 
100  void dropGood(Transaction const& _t);
101 
102  struct Status
103  {
104  size_t current;
105  size_t future;
106  size_t unverified;
107  size_t dropped;
108  };
110  Status status() const { Status ret; DEV_GUARDED(x_queue) { ret.unverified = m_unverified.size(); } ReadGuard l(m_lock); ret.dropped = m_dropped.size(); ret.current = m_currentByHash.size(); ret.future = m_future.size(); return ret; }
111 
113  Limits limits() const { return Limits{m_limit, m_futureLimit}; }
114 
116  void clear();
117 
119  template <class T> Handler<> onReady(T const& _t) { return m_onReady.add(_t); }
120 
122  template <class T> Handler<ImportResult, h256 const&, h512 const&> onImport(T const& _t) { return m_onImport.add(_t); }
123 
125  template <class T> Handler<h256 const&> onReplaced(T const& _t) { return m_onReplaced.add(_t); }
126 
127 private:
128 
130  struct VerifiedTransaction
131  {
132  VerifiedTransaction(Transaction const& _t): transaction(_t) {}
133  VerifiedTransaction(VerifiedTransaction&& _t): transaction(std::move(_t.transaction)) {}
134 
135  VerifiedTransaction(VerifiedTransaction const&) = delete;
136  VerifiedTransaction& operator=(VerifiedTransaction const&) = delete;
137 
138  Transaction transaction;
139  };
140 
142  struct UnverifiedTransaction
143  {
144  UnverifiedTransaction() {}
145  UnverifiedTransaction(bytesConstRef const& _t, h512 const& _nodeId): transaction(_t.toBytes()), nodeId(_nodeId) {}
146  UnverifiedTransaction(UnverifiedTransaction&& _t): transaction(std::move(_t.transaction)), nodeId(std::move(_t.nodeId)) {}
147  UnverifiedTransaction& operator=(UnverifiedTransaction&& _other)
148  {
149  assert(&_other != this);
150 
151  transaction = std::move(_other.transaction);
152  nodeId = std::move(_other.nodeId);
153  return *this;
154  }
155 
156  UnverifiedTransaction(UnverifiedTransaction const&) = delete;
157  UnverifiedTransaction& operator=(UnverifiedTransaction const&) = delete;
158 
159  bytes transaction;
160  h512 nodeId;
161  };
162 
163  struct PriorityCompare
164  {
165  TransactionQueue& queue;
167  bool operator()(VerifiedTransaction const& _first, VerifiedTransaction const& _second) const
168  {
169  u256 const& height1 = _first.transaction.nonce() - queue.m_currentByAddressAndNonce[_first.transaction.sender()].begin()->first;
170  u256 const& height2 = _second.transaction.nonce() - queue.m_currentByAddressAndNonce[_second.transaction.sender()].begin()->first;
171  return height1 < height2 || (height1 == height2 && _first.transaction.gasPrice() > _second.transaction.gasPrice());
172  }
173  };
174 
175  // Use a set with dynamic comparator for minmax priority queue. The comparator takes into account min account nonce. Updating it does not affect the order.
176  using PriorityQueue = std::multiset<VerifiedTransaction, PriorityCompare>;
177 
179  ImportResult check_WITH_LOCK(h256 const& _h, IfDropped _ik);
180  ImportResult manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction);
181 
182  void insertCurrent_WITH_LOCK(std::pair<h256, Transaction> const& _p);
183  void makeCurrent_WITH_LOCK(Transaction const& _t);
184  bool remove_WITH_LOCK(h256 const& _txHash);
185  u256 maxNonce_WITH_LOCK(Address const& _a) const;
186  void verifierBody();
187 
188  mutable SharedMutex m_lock;
189  h256Hash m_known;
190 
191  std::unordered_map<h256, std::function<void(ImportResult)>> m_callbacks;
192  h256Hash m_dropped;
193 
194  PriorityQueue m_current;
195  std::unordered_map<h256, PriorityQueue::iterator> m_currentByHash;
196  std::unordered_map<Address, std::map<u256, PriorityQueue::iterator>> m_currentByAddressAndNonce;
197  std::unordered_map<Address, std::map<u256, VerifiedTransaction>> m_future;
198 
199  Signal<> m_onReady;
200  Signal<ImportResult, h256 const&, h512 const&> m_onImport;
201  Signal<h256 const&> m_onReplaced;
202  unsigned m_limit;
203  unsigned m_futureLimit;
204  unsigned m_futureSize = 0;
205 
206  std::condition_variable m_queueReady;
207  std::vector<std::thread> m_verifiers;
208  std::deque<UnverifiedTransaction> m_unverified;
209  mutable Mutex x_queue;
210  std::atomic<bool> m_aborting = {false};
211 
212  Logger m_logger{createLogger(VerbosityInfo, "tq")};
213  Logger m_loggerDetail{createLogger(VerbosityDebug, "tq")};
214 };
215 
216 }
217 }
218 
Definition: Address.cpp:20
u256 maxNonce(Address const &_a) const
A queue of Transactions, each stored as RLP. Maintains a transaction queue sorted by nonce diff and g...
Handler< ImportResult, h256 const &, h512 const & > onImport(T const &_t)
Register a handler that will be called once asynchronous verification is comeplte an transaction has ...
void enqueue(RLP const &_data, h512 const &_nodeId)
TransactionQueue(Limits const &_l)
Handler onReady(T const &_t)
Register a handler that will be called once there is a new transaction imported.
h160 Address
Definition: Address.h:30
void drop(h256 const &_txHash)
std::vector< Transaction > Transactions
Nice name for vector of Transaction.
Definition: Transaction.h:122
Definition: FixedHash.h:390
FixedHash< 64 > h512
Definition: FixedHash.h:353
ImportResult
Definition: Common.h:115
#define DEV_GUARDED(MUTEX)
Simple block guard. The expression/block following is guarded though the given mutex. Usage:
Definition: Guards.h:132
IfDropped
Import transaction policy.
Definition: Common.h:233
std::shared_ptr< typename Signal< Args... >::HandlerAux > Handler
Definition: Common.h:200
unsigned waiting(Address const &_a) const
Logger createLogger(int _severity, std::string const &_channel)
Definition: Log.h:125
std::vector< byte > bytes
Definition: Common.h:72
vector_ref< byte const > bytesConstRef
Definition: Common.h:74
void clear()
Clear the queue.
Don&#39;t import transaction that was previously dropped.
std::shared_ptr< HandlerAux > add(Callback const &_h)
Definition: Common.h:181
FixedHash< 32 > h256
Definition: FixedHash.h:354
h256Hash knownTransactions() const
boost::shared_lock< boost::shared_mutex > ReadGuard
Definition: Guards.h:44
Encodes a transaction, ready to be exported to or freshly imported from RLP.
Definition: Transaction.h:85
void setFuture(h256 const &_t)
void dropGood(Transaction const &_t)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Definition: Common.h:121
boost::shared_mutex SharedMutex
Definition: Guards.h:39
Transactions topTransactions(unsigned _limit, h256Hash const &_avoid=h256Hash()) const
std::unordered_set< h256 > h256Hash
Definition: FixedHash.h:363
std::mutex Mutex
Definition: Guards.h:37
Handler< h256 const & > onReplaced(T const &_t)
Register a handler that will be called once asynchronous verification is comeplte an transaction has ...
Definition: RLP.h:47
boost::log::sources::severity_channel_logger<> Logger
Definition: Log.h:124
TransactionQueue(unsigned _limit=1024, unsigned _futureLimit=1024)
TransactionQueue.