Fabcoin Core  0.16.2
P2P Digital Currency
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 
39 struct TransactionQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; };
40 struct TransactionQueueTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 7; };
41 #define ctxq dev::LogOutputStream<dev::eth::TransactionQueueTraceChannel, true>()
42 
49 {
50 public:
51  struct Limits { size_t current; size_t future; };
52 
56  TransactionQueue(unsigned _limit = 1024, unsigned _futureLimit = 1024);
57  TransactionQueue(Limits const& _l): TransactionQueue(_l.current, _l.future) {}
62  void enqueue(RLP const& _data, h512 const& _nodeId);
63 
68  ImportResult import(bytes const& _tx, IfDropped _ik = IfDropped::Ignore) { return import(&_tx, _ik); }
69 
74  ImportResult import(Transaction const& _tx, IfDropped _ik = IfDropped::Ignore);
75 
78  void drop(h256 const& _txHash);
79 
82  unsigned waiting(Address const& _a) const;
83 
88  Transactions topTransactions(unsigned _limit, h256Hash const& _avoid = h256Hash()) const;
89 
92  h256Hash knownTransactions() const;
93 
96  u256 maxNonce(Address const& _a) const;
97 
100  void setFuture(h256 const& _t);
101 
104  void dropGood(Transaction const& _t);
105 
106  struct Status
107  {
108  size_t current;
109  size_t future;
110  size_t unverified;
111  size_t dropped;
112  };
114  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; }
115 
117  Limits limits() const { return Limits{m_limit, m_futureLimit}; }
118 
120  void clear();
121 
123  template <class T> Handler<> onReady(T const& _t) { return m_onReady.add(_t); }
124 
126  template <class T> Handler<ImportResult, h256 const&, h512 const&> onImport(T const& _t) { return m_onImport.add(_t); }
127 
129  template <class T> Handler<h256 const&> onReplaced(T const& _t) { return m_onReplaced.add(_t); }
130 
131 private:
132 
135  {
136  VerifiedTransaction(Transaction const& _t): transaction(_t) {}
137  VerifiedTransaction(VerifiedTransaction&& _t): transaction(std::move(_t.transaction)) {}
138 
139  VerifiedTransaction(VerifiedTransaction const&) = delete;
140  VerifiedTransaction& operator=(VerifiedTransaction const&) = delete;
141 
143  };
144 
147  {
149  UnverifiedTransaction(bytesConstRef const& _t, h512 const& _nodeId): transaction(_t.toBytes()), nodeId(_nodeId) {}
150  UnverifiedTransaction(UnverifiedTransaction&& _t): transaction(std::move(_t.transaction)), nodeId(std::move(_t.nodeId)) {}
152  {
153  assert(&_other != this);
154 
155  transaction = std::move(_other.transaction);
156  nodeId = std::move(_other.nodeId);
157  return *this;
158  }
159 
161  UnverifiedTransaction& operator=(UnverifiedTransaction const&) = delete;
162 
165  };
166 
168  {
171  bool operator()(VerifiedTransaction const& _first, VerifiedTransaction const& _second) const
172  {
173  u256 const& height1 = _first.transaction.nonce() - queue.m_currentByAddressAndNonce[_first.transaction.sender()].begin()->first;
174  u256 const& height2 = _second.transaction.nonce() - queue.m_currentByAddressAndNonce[_second.transaction.sender()].begin()->first;
175  return height1 < height2 || (height1 == height2 && _first.transaction.gasPrice() > _second.transaction.gasPrice());
176  }
177  };
178 
179  // 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.
180  using PriorityQueue = std::multiset<VerifiedTransaction, PriorityCompare>;
181 
183  ImportResult check_WITH_LOCK(h256 const& _h, IfDropped _ik);
184  ImportResult manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction);
185 
186  void insertCurrent_WITH_LOCK(std::pair<h256, Transaction> const& _p);
187  void makeCurrent_WITH_LOCK(Transaction const& _t);
188  bool remove_WITH_LOCK(h256 const& _txHash);
189  u256 maxNonce_WITH_LOCK(Address const& _a) const;
190  void verifierBody();
191 
192  mutable SharedMutex m_lock;
194 
195  std::unordered_map<h256, std::function<void(ImportResult)>> m_callbacks;
197 
199  std::unordered_map<h256, PriorityQueue::iterator> m_currentByHash;
200  std::unordered_map<Address, std::map<u256, PriorityQueue::iterator>> m_currentByAddressAndNonce;
201  std::unordered_map<Address, std::map<u256, VerifiedTransaction>> m_future;
202 
206  unsigned m_limit;
207  unsigned m_futureLimit;
208  unsigned m_futureSize = 0;
209 
210  std::condition_variable m_queueReady;
211  std::vector<std::thread> m_verifiers;
212  std::deque<UnverifiedTransaction> m_unverified;
213  mutable Mutex x_queue;
214  std::atomic<bool> m_aborting = {false};
215 };
216 
217 }
218 }
219 
SharedMutex m_lock
General lock.
unsigned m_limit
Max number of pending transactions.
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
h256Hash m_dropped
Transactions that have previously been dropped.
Super-duper signal mechanism. TODO: replace with somthing a bit heavier weight.
Definition: Common.h:133
A queue of Transactions, each stored as RLP.
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 ...
std::unordered_map< Address, std::map< u256, VerifiedTransaction > > m_future
std::unordered_map< h256, PriorityQueue::iterator > m_currentByHash
Transaction hash to set ref.
TransactionQueue(Limits const &_l)
unsigned m_futureLimit
Max number of future transactions.
#define T(i, x)
Handler onReady(T const &_t)
Register a handler that will be called once there is a new transaction imported.
UnverifiedTransaction & operator=(UnverifiedTransaction &&_other)
std::vector< Transaction > Transactions
Nice name for vector of Transaction.
Definition: Transaction.h:121
std::vector< std::thread > m_verifiers
Address const & sender() const
std::hash for asio::adress
Definition: Common.h:323
assert(len-trim+(2 *lenIndices)<=WIDTH)
Signal< ImportResult, h256 const &, h512 const & > m_onImport
Called for each import attempt. Arguments are result, transaction id an node id. Be nice and exit fas...
Mutex x_queue
Verification queue mutex.
Signal< h256 const & > m_onReplaced
Called whan transction is dropped during a call to import() to make room for another transaction...
bytes transaction
RLP encoded transaction data.
ImportResult
Definition: Common.h:97
#define DEV_GUARDED(MUTEX)
Simple block guard.
Definition: Guards.h:144
Verified and imported transaction.
std::deque< UnverifiedTransaction > m_unverified
Pending verification queue.
h256Hash m_known
Headers of transactions in both sets.
IfDropped
Import transaction policy.
Definition: Common.h:214
std::unordered_map< h256, std::function< void(ImportResult)> > m_callbacks
Called once.
std::multiset< VerifiedTransaction, PriorityCompare > PriorityQueue
std::shared_ptr< typename Signal< Args... >::HandlerAux > Handler
Definition: Common.h:181
std::vector< byte > bytes
Definition: Common.h:75
Don&#39;t import transaction that was previously dropped.
bool operator()(VerifiedTransaction const &_first, VerifiedTransaction const &_second) const
Compare transaction by nonce height and gas price.
std::unordered_map< Address, std::map< u256, PriorityQueue::iterator > > m_currentByAddressAndNonce
Transactions grouped by account and nonce.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
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:84
boost::shared_mutex SharedMutex
Definition: Guards.h:39
UnverifiedTransaction(bytesConstRef const &_t, h512 const &_nodeId)
The default logging channels.
Definition: Log.h:130
h512 nodeId
Network Id of the peer transaction comes from.
std::unordered_set< h256 > h256Hash
Definition: FixedHash.h:349
std::mutex Mutex
Definition: Guards.h:37
Signal m_onReady
Future transactions.
std::condition_variable m_queueReady
Signaled when m_unverified has a new entry.
Handler< h256 const & > onReplaced(T const &_t)
Register a handler that will be called once asynchronous verification is comeplte an transaction has ...
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64