Fabcoin Core  0.16.2
P2P Digital Currency
EthereumHost.cpp
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 #include "EthereumHost.h"
23 
24 #include <chrono>
25 #include <thread>
26 #include <libdevcore/Common.h>
27 #include <libp2p/Host.h>
28 #include <libp2p/Session.h>
29 #include <libethcore/Exceptions.h>
30 #include "BlockChain.h"
31 #include "TransactionQueue.h"
32 #include "BlockQueue.h"
33 #include "EthereumPeer.h"
34 #include "BlockChainSync.h"
35 
36 using namespace std;
37 using namespace dev;
38 using namespace dev::eth;
39 using namespace p2p;
40 
41 unsigned const EthereumHost::c_oldProtocolVersion = 62; //TODO: remove this once v63+ is common
42 static unsigned const c_maxSendTransactions = 256;
43 
44 char const* const EthereumHost::s_stateNames[static_cast<int>(SyncState::Size)] = {"NotSynced", "Idle", "Waiting", "Blocks", "State", "NewBlocks" };
45 
46 #if defined(_WIN32)
47 const char* EthereumHostTrace::name() { return EthPurple "^" EthGray " "; }
48 #else
49 const char* EthereumHostTrace::name() { return EthPurple "⧫" EthGray " "; }
50 #endif
51 
52 namespace
53 {
54 class EthereumPeerObserver: public EthereumPeerObserverFace
55 {
56 public:
57  EthereumPeerObserver(BlockChainSync& _sync, RecursiveMutex& _syncMutex, TransactionQueue& _tq): m_sync(_sync), m_syncMutex(_syncMutex), m_tq(_tq) {}
58 
59  void onPeerStatus(std::shared_ptr<EthereumPeer> _peer) override
60  {
61  RecursiveGuard l(m_syncMutex);
62  try
63  {
64  m_sync.onPeerStatus(_peer);
65  }
66  catch (FailedInvariant const&)
67  {
68  // "fix" for https://github.com/ethereum/webthree-umbrella/issues/300
69  clog(NetWarn) << "Failed invariant during sync, restarting sync";
70  m_sync.restartSync();
71  }
72  }
73 
74  void onPeerTransactions(std::shared_ptr<EthereumPeer> _peer, RLP const& _r) override
75  {
76  unsigned itemCount = _r.itemCount();
77  clog(EthereumHostTrace) << "Transactions (" << dec << itemCount << "entries)";
78  m_tq.enqueue(_r, _peer->id());
79  }
80 
81  void onPeerAborting() override
82  {
83  RecursiveGuard l(m_syncMutex);
84  try
85  {
86  m_sync.onPeerAborting();
87  }
88  catch (Exception&)
89  {
90  cwarn << "Exception on peer destruciton: " << boost::current_exception_diagnostic_information();
91  }
92  }
93 
94  void onPeerBlockHeaders(std::shared_ptr<EthereumPeer> _peer, RLP const& _headers) override
95  {
96  RecursiveGuard l(m_syncMutex);
97  try
98  {
99  m_sync.onPeerBlockHeaders(_peer, _headers);
100  }
101  catch (FailedInvariant const&)
102  {
103  // "fix" for https://github.com/ethereum/webthree-umbrella/issues/300
104  clog(NetWarn) << "Failed invariant during sync, restarting sync";
105  m_sync.restartSync();
106  }
107  }
108 
109  void onPeerBlockBodies(std::shared_ptr<EthereumPeer> _peer, RLP const& _r) override
110  {
111  RecursiveGuard l(m_syncMutex);
112  try
113  {
114  m_sync.onPeerBlockBodies(_peer, _r);
115  }
116  catch (FailedInvariant const&)
117  {
118  // "fix" for https://github.com/ethereum/webthree-umbrella/issues/300
119  clog(NetWarn) << "Failed invariant during sync, restarting sync";
120  m_sync.restartSync();
121  }
122  }
123 
124  void onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, std::vector<std::pair<h256, u256>> const& _hashes) override
125  {
126  RecursiveGuard l(m_syncMutex);
127  try
128  {
129  m_sync.onPeerNewHashes(_peer, _hashes);
130  }
131  catch (FailedInvariant const&)
132  {
133  // "fix" for https://github.com/ethereum/webthree-umbrella/issues/300
134  clog(NetWarn) << "Failed invariant during sync, restarting sync";
135  m_sync.restartSync();
136  }
137  }
138 
139  void onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r) override
140  {
141  RecursiveGuard l(m_syncMutex);
142  try
143  {
144  m_sync.onPeerNewBlock(_peer, _r);
145  }
146  catch (FailedInvariant const&)
147  {
148  // "fix" for https://github.com/ethereum/webthree-umbrella/issues/300
149  clog(NetWarn) << "Failed invariant during sync, restarting sync";
150  m_sync.restartSync();
151  }
152  }
153 
154  void onPeerNodeData(std::shared_ptr<EthereumPeer> /* _peer */, RLP const& _r) override
155  {
156  unsigned itemCount = _r.itemCount();
157  clog(EthereumHostTrace) << "Node Data (" << dec << itemCount << "entries)";
158  }
159 
160  void onPeerReceipts(std::shared_ptr<EthereumPeer> /* _peer */, RLP const& _r) override
161  {
162  unsigned itemCount = _r.itemCount();
163  clog(EthereumHostTrace) << "Receipts (" << dec << itemCount << "entries)";
164  }
165 
166 private:
167  BlockChainSync& m_sync;
168  RecursiveMutex& m_syncMutex;
169  TransactionQueue& m_tq;
170 };
171 
172 class EthereumHostData: public EthereumHostDataFace
173 {
174 public:
175  EthereumHostData(BlockChain const& _chain, OverlayDB const& _db): m_chain(_chain), m_db(_db) {}
176 
177  pair<bytes, unsigned> blockHeaders(RLP const& _blockId, unsigned _maxHeaders, u256 _skip, bool _reverse) const override
178  {
179  auto numHeadersToSend = _maxHeaders;
180 
181  auto step = static_cast<unsigned>(_skip) + 1;
182  assert(step > 0 && "step must not be 0");
183 
184  h256 blockHash;
185  if (_blockId.size() == 32) // block id is a hash
186  {
187  blockHash = _blockId.toHash<h256>();
188  clog(NetMessageSummary) << "GetBlockHeaders (block (hash): " << blockHash
189  << ", maxHeaders: " << _maxHeaders
190  << ", skip: " << _skip << ", reverse: " << _reverse << ")";
191 
192  if (!m_chain.isKnown(blockHash))
193  blockHash = {};
194  else if (!_reverse)
195  {
196  auto n = m_chain.number(blockHash);
197  if (numHeadersToSend == 0)
198  blockHash = {};
199  else if (n != 0 || blockHash == m_chain.genesisHash())
200  {
201  auto top = n + uint64_t(step) * numHeadersToSend - 1;
202  auto lastBlock = m_chain.number();
203  if (top > lastBlock)
204  {
205  numHeadersToSend = (lastBlock - n) / step + 1;
206  top = n + step * (numHeadersToSend - 1);
207  }
208  assert(top <= lastBlock && "invalid top block calculated");
209  blockHash = m_chain.numberHash(static_cast<unsigned>(top)); // override start block hash with the hash of the top block we have
210  }
211  else
212  blockHash = {};
213  }
214  }
215  else // block id is a number
216  {
217  auto n = _blockId.toInt<bigint>();
218  clog(NetMessageSummary) << "GetBlockHeaders (" << n
219  << "max: " << _maxHeaders
220  << "skip: " << _skip << (_reverse ? "reverse" : "") << ")";
221 
222  if (!_reverse)
223  {
224  auto lastBlock = m_chain.number();
225  if (n > lastBlock || numHeadersToSend == 0)
226  blockHash = {};
227  else
228  {
229  bigint top = n + uint64_t(step) * (numHeadersToSend - 1);
230  if (top > lastBlock)
231  {
232  numHeadersToSend = (lastBlock - static_cast<unsigned>(n)) / step + 1;
233  top = n + step * (numHeadersToSend - 1);
234  }
235  assert(top <= lastBlock && "invalid top block calculated");
236  blockHash = m_chain.numberHash(static_cast<unsigned>(top)); // override start block hash with the hash of the top block we have
237  }
238  }
239  else if (n <= std::numeric_limits<unsigned>::max())
240  blockHash = m_chain.numberHash(static_cast<unsigned>(n));
241  else
242  blockHash = {};
243  }
244 
245  auto nextHash = [this](h256 _h, unsigned _step)
246  {
247  static const unsigned c_blockNumberUsageLimit = 1000;
248 
249  const auto lastBlock = m_chain.number();
250  const auto limitBlock = lastBlock > c_blockNumberUsageLimit ? lastBlock - c_blockNumberUsageLimit : 0; // find the number of the block below which we don't expect BC changes.
251 
252  while (_step) // parent hash traversal
253  {
254  auto details = m_chain.details(_h);
255  if (details.number < limitBlock)
256  break; // stop using parent hash traversal, fallback to using block numbers
257  _h = details.parent;
258  --_step;
259  }
260 
261  if (_step) // still need lower block
262  {
263  auto n = m_chain.number(_h);
264  if (n >= _step)
265  _h = m_chain.numberHash(n - _step);
266  else
267  _h = {};
268  }
269 
270 
271  return _h;
272  };
273 
274  bytes rlp;
275  unsigned itemCount = 0;
276  vector<h256> hashes;
277  for (unsigned i = 0; i != numHeadersToSend; ++i)
278  {
279  if (!blockHash || !m_chain.isKnown(blockHash))
280  break;
281 
282  hashes.push_back(blockHash);
283  ++itemCount;
284 
285  blockHash = nextHash(blockHash, step);
286  }
287 
288  for (unsigned i = 0; i < hashes.size() && rlp.size() < c_maxPayload; ++i)
289  rlp += m_chain.headerData(hashes[_reverse ? i : hashes.size() - 1 - i]);
290 
291  return make_pair(rlp, itemCount);
292  }
293 
294  pair<bytes, unsigned> blockBodies(RLP const& _blockHashes) const override
295  {
296  unsigned const count = static_cast<unsigned>(_blockHashes.itemCount());
297 
298  bytes rlp;
299  unsigned n = 0;
300  auto numBodiesToSend = std::min(count, c_maxBlocks);
301  for (unsigned i = 0; i < numBodiesToSend && rlp.size() < c_maxPayload; ++i)
302  {
303  auto h = _blockHashes[i].toHash<h256>();
304  if (m_chain.isKnown(h))
305  {
306  bytes blockBytes = m_chain.block(h);
307  RLP block{blockBytes};
308  RLPStream body;
309  body.appendList(2);
310  body.appendRaw(block[1].data()); // transactions
311  body.appendRaw(block[2].data()); // uncles
312  auto bodyBytes = body.out();
313  rlp.insert(rlp.end(), bodyBytes.begin(), bodyBytes.end());
314  ++n;
315  }
316  }
317  if (count > 20 && n == 0)
318  clog(NetWarn) << "all" << count << "unknown blocks requested; peer on different chain?";
319  else
320  clog(NetMessageSummary) << n << "blocks known and returned;" << (numBodiesToSend - n) << "blocks unknown;" << (count > c_maxBlocks ? count - c_maxBlocks : 0) << "blocks ignored";
321 
322  return make_pair(rlp, n);
323  }
324 
325  strings nodeData(RLP const& _dataHashes) const override
326  {
327  unsigned const count = static_cast<unsigned>(_dataHashes.itemCount());
328 
329  strings data;
330  size_t payloadSize = 0;
331  auto numItemsToSend = std::min(count, c_maxNodes);
332  for (unsigned i = 0; i < numItemsToSend && payloadSize < c_maxPayload; ++i)
333  {
334  auto h = _dataHashes[i].toHash<h256>();
335  auto node = m_db.lookup(h);
336  if (!node.empty())
337  {
338  payloadSize += node.length();
339  data.push_back(move(node));
340  }
341  }
342  clog(NetMessageSummary) << data.size() << " nodes known and returned;" << (numItemsToSend - data.size()) << " unknown;" << (count > c_maxNodes ? count - c_maxNodes : 0) << " ignored";
343 
344  return data;
345  }
346 
347  pair<bytes, unsigned> receipts(RLP const& _blockHashes) const override
348  {
349  unsigned const count = static_cast<unsigned>(_blockHashes.itemCount());
350 
351  bytes rlp;
352  unsigned n = 0;
353  auto numItemsToSend = std::min(count, c_maxReceipts);
354  for (unsigned i = 0; i < numItemsToSend && rlp.size() < c_maxPayload; ++i)
355  {
356  auto h = _blockHashes[i].toHash<h256>();
357  if (m_chain.isKnown(h))
358  {
359  auto const receipts = m_chain.receipts(h);
360  auto receiptsRlpList = receipts.rlp();
361  rlp.insert(rlp.end(), receiptsRlpList.begin(), receiptsRlpList.end());
362  ++n;
363  }
364  }
365  clog(NetMessageSummary) << n << " receipt lists known and returned;" << (numItemsToSend - n) << " unknown;" << (count > c_maxReceipts ? count - c_maxReceipts : 0) << " ignored";
366 
367  return make_pair(rlp, n);
368  }
369 
370 private:
371  BlockChain const& m_chain;
372  OverlayDB const& m_db;
373 };
374 
375 }
376 
377 EthereumHost::EthereumHost(BlockChain const& _ch, OverlayDB const& _db, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId):
378  HostCapability<EthereumPeer>(),
379  Worker ("ethsync"),
380  m_chain (_ch),
381  m_db(_db),
382  m_tq (_tq),
383  m_bq (_bq),
384  m_networkId (_networkId),
385  m_hostData(make_shared<EthereumHostData>(m_chain, m_db))
386 {
387  // TODO: Composition would be better. Left like that to avoid initialization
388  // issues as BlockChainSync accesses other EthereumHost members.
389  m_sync.reset(new BlockChainSync(*this));
390  m_peerObserver = make_shared<EthereumPeerObserver>(*m_sync, x_sync, m_tq);
392  m_tq.onImport([this](ImportResult _ir, h256 const& _h, h512 const& _nodeId) { onTransactionImported(_ir, _h, _nodeId); });
393 }
394 
396 {
397 }
398 
400 {
401  if (!m_latestBlockSent)
402  {
403  // First time - just initialise.
405  clog(EthereumHostTrace) << "Initialising: latest=" << m_latestBlockSent;
406 
409  return true;
410  }
411  return false;
412 }
413 
415 {
417  m_sync->abortSync();
418 
420  Guard tl(x_transactions);
421  m_transactionsSent.clear();
422 }
423 
425 {
427  m_sync->completeSync();
428 }
429 
431 {
432  bool netChange = ensureInitialised();
433  auto h = m_chain.currentHash();
434  // If we've finished our initial sync (including getting all the blocks into the chain so as to reduce invalid transactions), start trading transactions & blocks
436  {
437  if (m_newTransactions)
438  {
439  m_newTransactions = false;
441  }
442  if (m_newBlocks)
443  {
444  m_newBlocks = false;
445  maintainBlocks(h);
446  }
447  }
448 
449  time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
450  if (now - m_lastTick >= 1)
451  {
452  m_lastTick = now;
453  foreachPeer([](std::shared_ptr<EthereumPeer> _p) { _p->tick(); return true; });
454  }
455 
456 // return netChange;
457  // TODO: Figure out what to do with netChange.
458  (void)netChange;
459 }
460 
462 {
463  // Send any new transactions.
464  unordered_map<std::shared_ptr<EthereumPeer>, std::vector<size_t>> peerTransactions;
465  auto ts = m_tq.topTransactions(c_maxSendTransactions);
466  {
468  for (size_t i = 0; i < ts.size(); ++i)
469  {
470  auto const& t = ts[i];
471  bool unsent = !m_transactionsSent.count(t.sha3());
472  auto peers = get<1>(randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(t.sha3())); }));
473  for (auto const& p: peers)
474  peerTransactions[p].push_back(i);
475  }
476  for (auto const& t: ts)
477  m_transactionsSent.insert(t.sha3());
478  }
479  foreachPeer([&](shared_ptr<EthereumPeer> _p)
480  {
481  bytes b;
482  unsigned n = 0;
483  for (auto const& i: peerTransactions[_p])
484  {
485  _p->m_knownTransactions.insert(ts[i].sha3());
486  b += ts[i].rlp();
487  ++n;
488  }
489 
490  _p->clearKnownTransactions();
491 
492  if (n || _p->m_requireTransactions)
493  {
494  RLPStream ts;
495  _p->prep(ts, TransactionsPacket, n).appendRaw(b, n);
496  _p->sealAndSend(ts);
497  clog(EthereumHostTrace) << "Sent" << n << "transactions to " << _p->session()->info().clientVersion;
498  }
499  _p->m_requireTransactions = false;
500  return true;
501  });
502 }
503 
504 void EthereumHost::foreachPeer(std::function<bool(std::shared_ptr<EthereumPeer>)> const& _f) const
505 {
506  //order peers by protocol, rating, connection age
507  auto sessions = peerSessions();
508  auto sessionLess = [](std::pair<std::shared_ptr<SessionFace>, std::shared_ptr<Peer>> const& _left, std::pair<std::shared_ptr<SessionFace>, std::shared_ptr<Peer>> const& _right)
509  { return _left.first->rating() == _right.first->rating() ? _left.first->connectionTime() < _right.first->connectionTime() : _left.first->rating() > _right.first->rating(); };
510 
511  std::sort(sessions.begin(), sessions.end(), sessionLess);
512  for (auto s: sessions)
513  if (!_f(capabilityFromSession<EthereumPeer>(*s.first)))
514  return;
515 
516  sessions = peerSessions(c_oldProtocolVersion); //TODO: remove once v61+ is common
517  std::sort(sessions.begin(), sessions.end(), sessionLess);
518  for (auto s: sessions)
519  if (!_f(capabilityFromSession<EthereumPeer>(*s.first, c_oldProtocolVersion)))
520  return;
521 }
522 
523 tuple<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<SessionFace>>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow)
524 {
525  vector<shared_ptr<EthereumPeer>> chosen;
526  vector<shared_ptr<EthereumPeer>> allowed;
527  vector<shared_ptr<SessionFace>> sessions;
528 
529  size_t peerCount = 0;
530  foreachPeer([&](std::shared_ptr<EthereumPeer> _p)
531  {
532  if (_allow(_p.get()))
533  {
534  allowed.push_back(_p);
535  sessions.push_back(_p->session());
536  }
537  ++peerCount;
538  return true;
539  });
540 
541  size_t chosenSize = (peerCount * _percent + 99) / 100;
542  chosen.reserve(chosenSize);
543  for (unsigned i = chosenSize; i && allowed.size(); i--)
544  {
545  unsigned n = rand() % allowed.size();
546  chosen.push_back(std::move(allowed[n]));
547  allowed.erase(allowed.begin() + n);
548  }
549  return make_tuple(move(chosen), move(allowed), move(sessions));
550 }
551 
552 void EthereumHost::maintainBlocks(h256 const& _currentHash)
553 {
554  // Send any new blocks.
555  auto detailsFrom = m_chain.details(m_latestBlockSent);
556  auto detailsTo = m_chain.details(_currentHash);
557  if (detailsFrom.totalDifficulty < detailsTo.totalDifficulty)
558  {
559  if (diff(detailsFrom.number, detailsTo.number) < 20)
560  {
561  // don't be sending more than 20 "new" blocks. if there are any more we were probably waaaay behind.
562  clog(EthereumHostTrace) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")";
563 
564  h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true));
565 
566  auto s = randomSelection(25, [&](EthereumPeer* p){
568  return !p->m_knownBlocks.count(_currentHash);
569  return false;
570  });
571  for (shared_ptr<EthereumPeer> const& p: get<0>(s))
572  for (auto const& b: blocks)
573  {
574  RLPStream ts;
576 
577  Guard l(p->x_knownBlocks);
578  p->sealAndSend(ts);
579  p->m_knownBlocks.clear();
580  }
581  for (shared_ptr<EthereumPeer> const& p: get<1>(s))
582  {
583  RLPStream ts;
584  p->prep(ts, NewBlockHashesPacket, blocks.size());
585  for (auto const& b: blocks)
586  {
587  ts.appendList(2);
588  ts.append(b);
589  ts.append(m_chain.number(b));
590  }
591 
592  Guard l(p->x_knownBlocks);
593  p->sealAndSend(ts);
594  p->m_knownBlocks.clear();
595  }
596  }
597  m_latestBlockSent = _currentHash;
598  }
599 }
600 
602 {
603  return m_sync->isSyncing();
604 }
605 
607 {
609  return m_sync->status();
610 }
611 
612 void EthereumHost::onTransactionImported(ImportResult _ir, h256 const& _h, h512 const& _nodeId)
613 {
614  auto session = host()->peerSession(_nodeId);
615  if (!session)
616  return;
617 
618  std::shared_ptr<EthereumPeer> peer = capabilityFromSession<EthereumPeer>(*session);
619  if (!peer)
620  peer = capabilityFromSession<EthereumPeer>(*session, c_oldProtocolVersion);
621  if (!peer)
622  return;
623 
624  Guard l(peer->x_knownTransactions);
625  peer->m_knownTransactions.insert(_h);
626  switch (_ir)
627  {
629  peer->addRating(-100);
630  break;
632  // if we already had the transaction, then don't bother sending it on.
634  m_transactionsSent.insert(_h);
635  peer->addRating(0);
636  break;
638  peer->addRating(100);
639  break;
640  default:;
641  }
642 }
643 
644 shared_ptr<Capability> EthereumHost::newPeerCapability(shared_ptr<SessionFace> const& _s, unsigned _idOffset, p2p::CapDesc const& _cap, uint16_t _capID)
645 {
646  auto ret = HostCapability<EthereumPeer>::newPeerCapability(_s, _idOffset, _cap, _capID);
647 
648  auto cap = capabilityFromSession<EthereumPeer>(*_s, _cap.second);
649  assert(cap);
650  cap->init(
651  protocolVersion(),
652  m_networkId,
656  m_hostData,
658  );
659 
660  return ret;
661 }
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
SyncStatus status() const
#define function(a, b, c, d, k, s)
std::atomic< time_t > m_lastTick
Definition: EthereumHost.h:138
std::tuple< h256s, h256, unsigned > treeRoute(h256 const &_from, h256 const &_to, bool _common=true, bool _pre=true, bool _post=true) const
BlockDetails details(h256 const &_hash) const
Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
Definition: BlockChain.h:156
A queue of Transactions, each stored as RLP.
std::vector< std::pair< std::shared_ptr< SessionFace >, std::shared_ptr< Peer > > > peerSessions() const
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 ...
virtual ~EthereumHost()
Will block on network process events.
virtual std::shared_ptr< Capability > newPeerCapability(std::shared_ptr< SessionFace > const &_s, unsigned _idOffset, CapDesc const &_cap, uint16_t _capID)
std::tuple< std::vector< std::shared_ptr< EthereumPeer > >, std::vector< std::shared_ptr< EthereumPeer > >, std::vector< std::shared_ptr< p2p::SessionFace > > > randomSelection(unsigned _percent=25, std::function< bool(EthereumPeer *)> const &_allow=[](EthereumPeer const *){return true;})
Implements the blockchain database.
Definition: BlockChain.h:105
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
Definition: RLP.h:467
std::pair< std::string, u256 > CapDesc
Definition: Common.h:142
size_t itemCount() const
Definition: RLP.h:118
void maintainBlocks(h256 const &_currentBlock)
RLPStream & append(unsigned _s)
Append given datum to the byte stream.
Definition: RLP.h:395
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<>> bigint
Definition: Common.h:121
#define h(i)
Definition: sha.cpp:736
bytes const & out() const
Read the byte stream.
Definition: RLP.h:433
size_t count
Definition: ExecStats.cpp:37
RecursiveMutex x_sync
Definition: EthereumHost.h:135
std::vector< std::string > strings
Definition: Common.h:147
std::hash for asio::adress
Definition: Common.h:323
assert(len-trim+(2 *lenIndices)<=WIDTH)
unsigned protocolVersion() const
Definition: EthereumHost.h:70
void onTransactionImported(ImportResult _ir, h256 const &_h, h512 const &_nodeId)
ExecStats::duration min
Definition: ExecStats.cpp:35
std::unique_ptr< BlockChainSync > m_sync
Definition: EthereumHost.h:137
#define EthPurple
Definition: Terminal.h:129
ImportResult
Definition: Common.h:97
std::recursive_mutex RecursiveMutex
Definition: Guards.h:38
Transactions topTransactions(unsigned _limit, h256Hash const &_avoid=h256Hash()) const
Get top transactions from the queue.
#define DEV_GUARDED(MUTEX)
Simple block guard.
Definition: Guards.h:144
virtual void doWork() override
Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from...
h256Hash m_knownBlocks
Blocks that the peer already knows about (that don&#39;t need to be sent to them).
Definition: EthereumPeer.h:189
_N toHash(int _flags=Strict) const
Definition: RLP.h:298
Base class for all exceptions.
Definition: Exceptions.h:39
static unsigned const c_oldProtocolVersion
Definition: EthereumHost.h:93
bool ensureInitialised()
Initialises the network peer-state, doing the stuff that needs to be once-only.
std::lock_guard< std::mutex > Guard
Definition: Guards.h:41
std::shared_ptr< EthereumHostDataFace > m_hostData
Definition: EthereumHost.h:140
unsigned number(h256 const &_hash) const
Get a number for the given hash (or the most recent mined if none given). Thread-safe.
Definition: BlockChain.h:225
void completeSync()
Don&#39;t sync further - used only in test mode.
const char * name
Definition: rest.cpp:36
BlockChain const & m_chain
Definition: EthereumHost.h:120
ExecStats::duration max
Definition: ExecStats.cpp:36
h256 currentHash() const
Get a given block (RLP format). Thread-safe.
Definition: BlockChain.h:229
std::vector< byte > bytes
Definition: Common.h:75
RLPStream & appendList(size_t _items)
Appends a list.
Definition: RLP.cpp:276
#define EthGray
Definition: Terminal.h:118
std::shared_ptr< EthereumPeerObserverFace > m_peerObserver
Definition: EthereumHost.h:141
FixedHash< 32 > h256
Definition: FixedHash.h:340
#define cwarn
Definition: Log.h:304
A queue of blocks.
Definition: BlockQueue.h:225
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
void foreachPeer(std::function< bool(std::shared_ptr< EthereumPeer >)> const &_f) const
TransactionQueue & m_tq
Maintains a list of incoming transactions not yet in a block on the blockchain.
Definition: EthereumHost.h:122
bool isKnown(h256 const &_hash, bool _isCurrent=true) const
Returns true if the given block is known (though not necessarily a part of the canon chain)...
#define b(i, j)
RLPStream & prep(RLPStream &_s, unsigned _id, unsigned _args=0)
Definition: Capability.cpp:43
Base BlockChain synchronization strategy class.
The EthereumPeer class.
Definition: EthereumPeer.h:83
void sealAndSend(RLPStream &_s)
Definition: Capability.cpp:48
bool m_requireTransactions
Have we received a GetTransactions packet that we haven&#39;t yet answered?
Definition: EthereumPeer.h:186
N diff(N const &_a, N const &_b)
Definition: Common.h:212
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
std::shared_ptr< p2p::Capability > newPeerCapability(std::shared_ptr< p2p::SessionFace > const &_s, unsigned _idOffset, p2p::CapDesc const &_cap, uint16_t _capID) override
#define clog(X)
Definition: Log.h:295
h256Hash m_knownTransactions
Transactions that the peer already knows of.
Definition: EthereumPeer.h:191
std::lock_guard< std::recursive_mutex > RecursiveGuard
Definition: Guards.h:43
h256 genesisHash() const
Get the hash of the genesis block. Thread-safe.
Definition: BlockChain.h:232
bytes block(h256 const &_hash) const
Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
std::vector< h256 > h256s
Definition: FixedHash.h:345
_T toInt(int _flags=Strict) const
Converts to int of type given; if isString(), decodes as big-endian bytestream.
Definition: RLP.h:275
Class for writing to an RLP bytestream.
Definition: RLP.h:383
RLPStream & appendRaw(bytesConstRef _rlp, size_t _itemCount=1)
Appends raw (pre-serialised) RLP data. Use with caution.
Definition: RLP.cpp:230
h256Hash knownTransactions() const
Get a hash set of transactions in the queue.
uint8_t const * data
Definition: sha3.h:19
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
size_t size() const
Definition: RLP.h:122
std::shared_ptr< SessionFace > peerSession(NodeID const &_id)
Get session by id.
Definition: Host.h:230
Definition: internal.h:25