EthereumPeer.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file EthereumPeer.cpp
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. */
  18. #include "EthereumPeer.h"
  19. #include <chrono>
  20. #include <libdevcore/Common.h>
  21. #include <libethcore/Exceptions.h>
  22. #include <libp2p/Session.h>
  23. #include <libp2p/Host.h>
  24. #include "BlockChain.h"
  25. #include "EthereumHost.h"
  26. #include "TransactionQueue.h"
  27. #include "BlockQueue.h"
  28. #include "BlockChainSync.h"
  29. using namespace std;
  30. using namespace dev;
  31. using namespace dev::eth;
  32. using namespace p2p;
  33. static const unsigned c_maxIncomingNewHashes = 1024;
  34. static const unsigned c_maxHeadersToSend = 1024;
  35. static string toString(Asking _a)
  36. {
  37. switch (_a)
  38. {
  39. case Asking::BlockHeaders: return "BlockHeaders";
  40. case Asking::BlockBodies: return "BlockBodies";
  41. case Asking::NodeData: return "NodeData";
  42. case Asking::Receipts: return "Receipts";
  43. case Asking::Nothing: return "Nothing";
  44. case Asking::State: return "State";
  45. }
  46. return "?";
  47. }
  48. EthereumPeer::EthereumPeer(std::shared_ptr<Session> _s, HostCapabilityFace* _h, unsigned _i, CapDesc const& _cap, uint16_t _capID):
  49. Capability(_s, _h, _i, _capID),
  50. m_peerCapabilityVersion(_cap.second)
  51. {
  52. session()->addNote("manners", isRude() ? "RUDE" : "nice");
  53. m_syncHashNumber = host()->chain().number() + 1;
  54. requestStatus();
  55. }
  56. EthereumPeer::~EthereumPeer()
  57. {
  58. if (m_asking != Asking::Nothing)
  59. {
  60. clog(NetAllDetail) << "Peer aborting while being asked for " << ::toString(m_asking);
  61. setRude();
  62. }
  63. abortSync();
  64. }
  65. bool EthereumPeer::isRude() const
  66. {
  67. auto s = session();
  68. if (s)
  69. return repMan().isRude(*s, name());
  70. return false;
  71. }
  72. unsigned EthereumPeer::askOverride() const
  73. {
  74. std::string static const badGeth = "Geth/v0.9.27";
  75. auto s = session();
  76. if (!s)
  77. return c_maxBlocksAsk;
  78. if (s->info().clientVersion.substr(0, badGeth.size()) == badGeth)
  79. return 1;
  80. bytes const& d = repMan().data(*s, name());
  81. return d.empty() ? c_maxBlocksAsk : RLP(d).toInt<unsigned>(RLP::LaissezFaire);
  82. }
  83. void EthereumPeer::setRude()
  84. {
  85. auto s = session();
  86. if (!s)
  87. return;
  88. auto old = askOverride();
  89. repMan().setData(*s, name(), rlp(askOverride() / 2 + 1));
  90. cnote << "Rude behaviour; askOverride now" << askOverride() << ", was" << old;
  91. repMan().noteRude(*s, name());
  92. session()->addNote("manners", "RUDE");
  93. }
  94. void EthereumPeer::abortSync()
  95. {
  96. host()->onPeerAborting();
  97. }
  98. EthereumHost* EthereumPeer::host() const
  99. {
  100. return static_cast<EthereumHost*>(Capability::hostCapability());
  101. }
  102. /*
  103. * Possible asking/syncing states for two peers:
  104. */
  105. void EthereumPeer::setIdle()
  106. {
  107. setAsking(Asking::Nothing);
  108. }
  109. void EthereumPeer::requestStatus()
  110. {
  111. assert(m_asking == Asking::Nothing);
  112. setAsking(Asking::State);
  113. m_requireTransactions = true;
  114. RLPStream s;
  115. bool latest = m_peerCapabilityVersion == host()->protocolVersion();
  116. prep(s, StatusPacket, 5)
  117. << (latest ? host()->protocolVersion() : EthereumHost::c_oldProtocolVersion)
  118. << host()->networkId()
  119. << host()->chain().details().totalDifficulty
  120. << host()->chain().currentHash()
  121. << host()->chain().genesisHash();
  122. sealAndSend(s);
  123. }
  124. void EthereumPeer::requestBlockHeaders(unsigned _startNumber, unsigned _count, unsigned _skip, bool _reverse)
  125. {
  126. if (m_asking != Asking::Nothing)
  127. {
  128. clog(NetWarn) << "Asking headers while requesting " << ::toString(m_asking);
  129. }
  130. setAsking(Asking::BlockHeaders);
  131. RLPStream s;
  132. prep(s, GetBlockHeadersPacket, 4) << _startNumber << _count << _skip << (_reverse ? 1 : 0);
  133. clog(NetMessageDetail) << "Requesting " << _count << " block headers starting from " << _startNumber << (_reverse ? " in reverse" : "");
  134. m_syncHashNumber = _startNumber;
  135. m_lastAskedHeaders = _count;
  136. sealAndSend(s);
  137. }
  138. void EthereumPeer::requestBlockHeaders(h256 const& _startHash, unsigned _count, unsigned _skip, bool _reverse)
  139. {
  140. if (m_asking != Asking::Nothing)
  141. {
  142. clog(NetWarn) << "Asking headers while requesting " << ::toString(m_asking);
  143. }
  144. setAsking(Asking::BlockHeaders);
  145. RLPStream s;
  146. prep(s, GetBlockHeadersPacket, 4) << _startHash << _count << _skip << (_reverse ? 1 : 0);
  147. clog(NetMessageDetail) << "Requesting " << _count << " block headers starting from " << _startHash << (_reverse ? " in reverse" : "");
  148. m_syncHash = _startHash;
  149. m_lastAskedHeaders = _count;
  150. sealAndSend(s);
  151. }
  152. void EthereumPeer::requestBlockBodies(h256s const& _blocks)
  153. {
  154. if (m_asking != Asking::Nothing)
  155. {
  156. clog(NetWarn) << "Asking headers while requesting " << ::toString(m_asking);
  157. }
  158. setAsking(Asking::BlockBodies);
  159. if (_blocks.size())
  160. {
  161. RLPStream s;
  162. prep(s, GetBlockBodiesPacket, _blocks.size());
  163. for (auto const& i: _blocks)
  164. s << i;
  165. sealAndSend(s);
  166. }
  167. else
  168. setIdle();
  169. }
  170. void EthereumPeer::setAsking(Asking _a)
  171. {
  172. m_asking = _a;
  173. m_lastAsk = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
  174. auto s = session();
  175. if (s)
  176. {
  177. s->addNote("ask", ::toString(_a));
  178. s->addNote("sync", string(isCriticalSyncing() ? "ONGOING" : "holding") + (needsSyncing() ? " & needed" : ""));
  179. }
  180. }
  181. void EthereumPeer::tick()
  182. {
  183. auto s = session();
  184. time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
  185. if (s && (now - m_lastAsk > 10 && m_asking != Asking::Nothing))
  186. // timeout
  187. s->disconnect(PingTimeout);
  188. }
  189. bool EthereumPeer::isConversing() const
  190. {
  191. return m_asking != Asking::Nothing;
  192. }
  193. bool EthereumPeer::isCriticalSyncing() const
  194. {
  195. return m_asking == Asking::BlockHeaders || m_asking == Asking::State || (m_asking == Asking::BlockBodies && m_protocolVersion == 62);
  196. }
  197. bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
  198. {
  199. m_lastAsk = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
  200. try
  201. {
  202. switch (_id)
  203. {
  204. case StatusPacket:
  205. {
  206. m_protocolVersion = _r[0].toInt<unsigned>();
  207. m_networkId = _r[1].toInt<u256>();
  208. m_totalDifficulty = _r[2].toInt<u256>();
  209. m_latestHash = _r[3].toHash<h256>();
  210. m_genesisHash = _r[4].toHash<h256>();
  211. if (m_peerCapabilityVersion == host()->protocolVersion())
  212. m_protocolVersion = host()->protocolVersion();
  213. clog(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << m_genesisHash << ", TD:" << m_totalDifficulty << "=" << m_latestHash;
  214. setIdle();
  215. host()->onPeerStatus(dynamic_pointer_cast<EthereumPeer>(dynamic_pointer_cast<EthereumPeer>(shared_from_this())));
  216. break;
  217. }
  218. case TransactionsPacket:
  219. {
  220. host()->onPeerTransactions(dynamic_pointer_cast<EthereumPeer>(dynamic_pointer_cast<EthereumPeer>(shared_from_this())), _r);
  221. break;
  222. }
  223. case GetBlockHeadersPacket:
  224. {
  225. /// Packet layout:
  226. /// [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ]
  227. const auto blockId = _r[0];
  228. const auto maxHeaders = _r[1].toInt<u256>();
  229. const auto skip = _r[2].toInt<u256>();
  230. const auto reverse = _r[3].toInt<bool>();
  231. auto& bc = host()->chain();
  232. auto numHeadersToSend = maxHeaders <= c_maxHeadersToSend ? static_cast<unsigned>(maxHeaders) : c_maxHeadersToSend;
  233. if (skip > std::numeric_limits<unsigned>::max() - 1)
  234. {
  235. clog(NetAllDetail) << "Requested block skip is too big: " << skip;
  236. break;
  237. }
  238. auto step = static_cast<unsigned>(skip) + 1;
  239. assert(step > 0 && "step must not be 0");
  240. h256 blockHash;
  241. if (blockId.size() == 32) // block id is a hash
  242. {
  243. blockHash = blockId.toHash<h256>();
  244. //blockNumber = host()->chain().number(blockHash);
  245. clog(NetMessageSummary) << "GetBlockHeaders (block (hash): " << blockHash
  246. << ", maxHeaders: " << maxHeaders
  247. << ", skip: " << skip << ", reverse: " << reverse << ")";
  248. if (!reverse)
  249. {
  250. auto n = bc.number(blockHash);
  251. if (numHeadersToSend == 0)
  252. blockHash = {};
  253. else if (n != 0 || blockHash == bc.genesisHash())
  254. {
  255. auto top = n + uint64_t(step) * numHeadersToSend - 1;
  256. auto lastBlock = bc.number();
  257. if (top > lastBlock)
  258. {
  259. numHeadersToSend = (lastBlock - n) / step + 1;
  260. top = n + step * (numHeadersToSend - 1);
  261. }
  262. assert(top <= lastBlock && "invalid top block calculated");
  263. blockHash = bc.numberHash(static_cast<unsigned>(top)); // override start block hash with the hash of the top block we have
  264. }
  265. else
  266. blockHash = {};
  267. }
  268. else if (!bc.isKnown(blockHash))
  269. blockHash = {};
  270. }
  271. else // block id is a number
  272. {
  273. auto n = blockId.toInt<bigint>();
  274. clog(NetMessageSummary) << "GetBlockHeaders (" << n
  275. << "max: " << maxHeaders
  276. << "skip: " << skip << (reverse ? "reverse" : "") << ")";
  277. if (!reverse)
  278. {
  279. auto lastBlock = bc.number();
  280. if (n > lastBlock || numHeadersToSend == 0)
  281. blockHash = {};
  282. else
  283. {
  284. bigint top = n + uint64_t(step) * (numHeadersToSend - 1);
  285. if (top > lastBlock)
  286. {
  287. numHeadersToSend = (lastBlock - static_cast<unsigned>(n)) / step + 1;
  288. top = n + step * (numHeadersToSend - 1);
  289. }
  290. assert(top <= lastBlock && "invalid top block calculated");
  291. blockHash = bc.numberHash(static_cast<unsigned>(top)); // override start block hash with the hash of the top block we have
  292. }
  293. }
  294. else if (n <= std::numeric_limits<unsigned>::max())
  295. blockHash = bc.numberHash(static_cast<unsigned>(n));
  296. else
  297. blockHash = {};
  298. }
  299. auto nextHash = [&bc](h256 _h, unsigned _step)
  300. {
  301. static const unsigned c_blockNumberUsageLimit = 1000;
  302. const auto lastBlock = bc.number();
  303. const auto limitBlock = lastBlock > c_blockNumberUsageLimit ? lastBlock - c_blockNumberUsageLimit : 0; // find the number of the block below which we don't expect BC changes.
  304. while (_step) // parent hash traversal
  305. {
  306. auto details = bc.details(_h);
  307. if (details.number < limitBlock)
  308. break; // stop using parent hash traversal, fallback to using block numbers
  309. _h = details.parent;
  310. --_step;
  311. }
  312. if (_step) // still need lower block
  313. {
  314. auto n = bc.number(_h);
  315. if (n >= _step)
  316. _h = bc.numberHash(n - _step);
  317. else
  318. _h = {};
  319. }
  320. return _h;
  321. };
  322. bytes rlp;
  323. unsigned itemCount = 0;
  324. vector<h256> hashes;
  325. for (unsigned i = 0; i != numHeadersToSend; ++i)
  326. {
  327. if (!blockHash || !bc.isKnown(blockHash))
  328. break;
  329. hashes.push_back(blockHash);
  330. ++itemCount;
  331. blockHash = nextHash(blockHash, step);
  332. }
  333. for (unsigned i = 0; i < hashes.size() && rlp.size() < c_maxPayload; ++i)
  334. rlp += bc.headerData(hashes[reverse ? i : hashes.size() - 1 - i]);
  335. RLPStream s;
  336. prep(s, BlockHeadersPacket, itemCount).appendRaw(rlp, itemCount);
  337. sealAndSend(s);
  338. addRating(0);
  339. break;
  340. }
  341. case BlockHeadersPacket:
  342. {
  343. if (m_asking != Asking::BlockHeaders)
  344. clog(NetImpolite) << "Peer giving us blocks when we didn't ask for them.";
  345. else
  346. {
  347. setIdle();
  348. host()->onPeerBlockHeaders(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
  349. }
  350. break;
  351. }
  352. case GetBlockBodiesPacket:
  353. {
  354. unsigned count = static_cast<unsigned>(_r.itemCount());
  355. clog(NetMessageSummary) << "GetBlockBodies (" << dec << count << "entries)";
  356. if (!count)
  357. {
  358. clog(NetImpolite) << "Zero-entry GetBlockBodies: Not replying.";
  359. addRating(-10);
  360. break;
  361. }
  362. // return the requested blocks.
  363. bytes rlp;
  364. unsigned n = 0;
  365. auto numBodiesToSend = std::min(count, c_maxBlocks);
  366. for (unsigned i = 0; i < numBodiesToSend && rlp.size() < c_maxPayload; ++i)
  367. {
  368. auto h = _r[i].toHash<h256>();
  369. if (host()->chain().isKnown(h))
  370. {
  371. bytes blockBytes = host()->chain().block(h);
  372. RLP block{blockBytes};
  373. RLPStream body;
  374. body.appendList(2);
  375. body.appendRaw(block[1].data()); // transactions
  376. body.appendRaw(block[2].data()); // uncles
  377. auto bodyBytes = body.out();
  378. rlp.insert(rlp.end(), bodyBytes.begin(), bodyBytes.end());
  379. ++n;
  380. }
  381. }
  382. if (count > 20 && n == 0)
  383. clog(NetWarn) << "all" << count << "unknown blocks requested; peer on different chain?";
  384. else
  385. clog(NetMessageSummary) << n << "blocks known and returned;" << (numBodiesToSend - n) << "blocks unknown;" << (count > c_maxBlocks ? count - c_maxBlocks : 0) << "blocks ignored";
  386. addRating(0);
  387. RLPStream s;
  388. prep(s, BlockBodiesPacket, n).appendRaw(rlp, n);
  389. sealAndSend(s);
  390. break;
  391. }
  392. case BlockBodiesPacket:
  393. {
  394. if (m_asking != Asking::BlockBodies)
  395. clog(NetImpolite) << "Peer giving us block bodies when we didn't ask for them.";
  396. else
  397. {
  398. setIdle();
  399. host()->onPeerBlockBodies(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
  400. }
  401. break;
  402. }
  403. case NewBlockPacket:
  404. {
  405. host()->onPeerNewBlock(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
  406. break;
  407. }
  408. case NewBlockHashesPacket:
  409. {
  410. unsigned itemCount = _r.itemCount();
  411. clog(NetMessageSummary) << "BlockHashes (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreHashes");
  412. if (itemCount > c_maxIncomingNewHashes)
  413. {
  414. disable("Too many new hashes");
  415. break;
  416. }
  417. vector<pair<h256, u256>> hashes(itemCount);
  418. for (unsigned i = 0; i < itemCount; ++i)
  419. hashes[i] = std::make_pair(_r[i][0].toHash<h256>(), _r[i][1].toInt<u256>());
  420. host()->onPeerNewHashes(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), hashes);
  421. break;
  422. }
  423. case GetNodeDataPacket:
  424. {
  425. unsigned count = static_cast<unsigned>(_r.itemCount());
  426. if (!count)
  427. {
  428. clog(NetImpolite) << "Zero-entry GetNodeData: Not replying.";
  429. addRating(-10);
  430. break;
  431. }
  432. clog(NetMessageSummary) << "GetNodeData (" << dec << count << " entries)";
  433. // return the requested nodes.
  434. strings data;
  435. unsigned n = 0;
  436. size_t payloadSize = 0;
  437. auto numItemsToSend = std::min(count, c_maxNodes);
  438. for (unsigned i = 0; i < numItemsToSend && payloadSize < c_maxPayload; ++i)
  439. {
  440. auto h = _r[i].toHash<h256>();
  441. auto node = host()->db().lookup(h);
  442. if (!node.empty())
  443. {
  444. payloadSize += node.length();
  445. data.push_back(move(node));
  446. ++n;
  447. }
  448. }
  449. clog(NetMessageSummary) << n << " nodes known and returned;" << (numItemsToSend - n) << " unknown;" << (count > c_maxNodes ? count - c_maxNodes : 0) << " ignored";
  450. addRating(0);
  451. RLPStream s;
  452. prep(s, NodeDataPacket, n);
  453. for (auto const& element: data)
  454. s.append(element);
  455. sealAndSend(s);
  456. break;
  457. }
  458. case GetReceiptsPacket:
  459. {
  460. unsigned count = static_cast<unsigned>(_r.itemCount());
  461. if (!count)
  462. {
  463. clog(NetImpolite) << "Zero-entry GetReceipts: Not replying.";
  464. addRating(-10);
  465. break;
  466. }
  467. clog(NetMessageSummary) << "GetReceipts (" << dec << count << " entries)";
  468. // return the requested receipts.
  469. bytes rlp;
  470. unsigned n = 0;
  471. auto numItemsToSend = std::min(count, c_maxReceipts);
  472. for (unsigned i = 0; i < numItemsToSend && rlp.size() < c_maxPayload; ++i)
  473. {
  474. auto h = _r[i].toHash<h256>();
  475. if (host()->chain().isKnown(h))
  476. {
  477. auto const receipts = host()->chain().receipts(h);
  478. auto receiptsRlpList = receipts.rlp();
  479. rlp.insert(rlp.end(), receiptsRlpList.begin(), receiptsRlpList.end());
  480. ++n;
  481. }
  482. }
  483. clog(NetMessageSummary) << n << " receipt lists known and returned;" << (numItemsToSend - n) << " unknown;" << (count > c_maxReceipts ? count - c_maxReceipts : 0) << " ignored";
  484. addRating(0);
  485. RLPStream s;
  486. prep(s, ReceiptsPacket, n).appendRaw(rlp, n);
  487. sealAndSend(s);
  488. break;
  489. }
  490. default:
  491. return false;
  492. }
  493. }
  494. catch (Exception const&)
  495. {
  496. clog(NetWarn) << "Peer causing an Exception:" << boost::current_exception_diagnostic_information() << _r;
  497. }
  498. catch (std::exception const& _e)
  499. {
  500. clog(NetWarn) << "Peer causing an exception:" << _e.what() << _r;
  501. }
  502. return true;
  503. }