1 // Aleth: Ethereum C++ client, tools and libraries. 2 // Copyright 2014-2019 Aleth Authors. 3 // Licensed under the GNU General Public License, Version 3. 4 #pragma once 5 6 #include "CommonNet.h" 7 #include "EthereumPeer.h" 8 #include <libdevcore/Guards.h> 9 #include <libdevcore/OverlayDB.h> 10 #include <libethcore/BlockHeader.h> 11 #include <libethcore/Common.h> 12 #include <libethereum/BlockChainSync.h> 13 #include <libethereum/VerifiedBlock.h> 14 #include <libp2p/Capability.h> 15 #include <libp2p/CapabilityHost.h> 16 #include <libp2p/Common.h> 17 #include <memory> 18 #include <mutex> 19 #include <random> 20 #include <thread> 21 #include <unordered_map> 22 #include <unordered_set> 23 #include <utility> 24 #include <vector> 25 26 namespace dev 27 { 28 29 class RLPStream; 30 31 namespace eth 32 { 33 34 class TransactionQueue; 35 class BlockQueue; 36 class BlockChainSync; 37 38 class EthereumPeerObserverFace 39 { 40 public: 41 virtual ~EthereumPeerObserverFace() = default; 42 43 virtual void onPeerStatus(EthereumPeer const& _peer) = 0; 44 45 virtual void onPeerTransactions(NodeID const& _peerID, RLP const& _r) = 0; 46 47 virtual void onPeerBlockHeaders(NodeID const& _peerID, RLP const& _headers) = 0; 48 49 virtual void onPeerBlockBodies(NodeID const& _peerID, RLP const& _r) = 0; 50 51 virtual void onPeerNewHashes( 52 NodeID const& _peerID, std::vector<std::pair<h256, u256>> const& _hashes) = 0; 53 54 virtual void onPeerNewBlock(NodeID const& _peerID, RLP const& _r) = 0; 55 56 virtual void onPeerNodeData(NodeID const& _peerID, RLP const& _r) = 0; 57 58 virtual void onPeerReceipts(NodeID const& _peerID, RLP const& _r) = 0; 59 60 virtual void onPeerAborting() = 0; 61 }; 62 63 class EthereumHostDataFace 64 { 65 public: 66 virtual ~EthereumHostDataFace() = default; 67 68 virtual std::pair<bytes, unsigned> blockHeaders( 69 RLP const& _blockId, unsigned _maxHeaders, u256 _skip, bool _reverse) const = 0; 70 71 virtual std::pair<bytes, unsigned> blockBodies(RLP const& _blockHashes) const = 0; 72 73 virtual strings nodeData(RLP const& _dataHashes) const = 0; 74 75 virtual std::pair<bytes, unsigned> receipts(RLP const& _blockHashes) const = 0; 76 }; 77 78 79 /** 80 * @brief The EthereumCapability class 81 * @warning None of this is thread-safe. You have been warned. 82 * @doWork Syncs to peers and sends new blocks and transactions. 83 */ 84 class EthereumCapability : public p2p::CapabilityFace 85 { 86 public: 87 /// Start server, but don't listen. 88 EthereumCapability(std::shared_ptr<p2p::CapabilityHostFace> _host, BlockChain const& _ch, 89 OverlayDB const& _db, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId); 90 name()91 std::string name() const override { return "eth"; } version()92 unsigned version() const override { return c_protocolVersion; } descriptor()93 p2p::CapDesc descriptor() const override { return {name(), version()}; } messageCount()94 unsigned messageCount() const override { return PacketCount; } packetTypeToString(unsigned _packetType)95 char const* packetTypeToString(unsigned _packetType) const override 96 { 97 return ethPacketTypeToString(static_cast<EthSubprotocolPacketType>(_packetType)); 98 } 99 std::chrono::milliseconds backgroundWorkInterval() const override; 100 protocolVersion()101 unsigned protocolVersion() const { return c_protocolVersion; } networkId()102 u256 networkId() const { return m_networkId; } setNetworkId(u256 _n)103 void setNetworkId(u256 _n) { m_networkId = _n; } 104 105 void reset(); 106 /// Don't sync further - used only in test mode 107 void completeSync(); 108 109 bool isSyncing() const; 110 noteNewTransactions()111 void noteNewTransactions() { m_newTransactions = true; } noteNewBlocks()112 void noteNewBlocks() { m_newBlocks = true; } onBlockImported(BlockHeader const & _info)113 void onBlockImported(BlockHeader const& _info) { m_sync->onBlockImported(_info); } 114 chain()115 BlockChain const& chain() const { return m_chain; } db()116 OverlayDB const& db() const { return m_db; } bq()117 BlockQueue& bq() { return m_bq; } bq()118 BlockQueue const& bq() const { return m_bq; } 119 SyncStatus status() const; 120 stateName(SyncState _s)121 static char const* stateName(SyncState _s) { return c_stateNames[static_cast<int>(_s)]; } 122 123 static unsigned const c_oldProtocolVersion; 124 125 void onConnect(NodeID const& _nodeID, u256 const& _peerCapabilityVersion) override; 126 void onDisconnect(NodeID const& _nodeID) override; 127 bool interpretCapabilityPacket(NodeID const& _peerID, unsigned _id, RLP const& _r) override; 128 129 /// Main work loop - sends new transactions and blocks to available peers and disconnects from 130 /// timed out peers 131 void doBackgroundWork() override; 132 capabilityHost()133 p2p::CapabilityHostFace& capabilityHost() { return *m_host; } 134 135 EthereumPeer const& peer(NodeID const& _peerID) const; 136 EthereumPeer& peer(NodeID const& _peerID); 137 void disablePeer(NodeID const& _peerID, std::string const& _problem); 138 139 /// Remove the supplied transaction hashes from the sent transactions list. Done when 140 /// the transactions have been confirmed to be a part of the blockchain so we no longer 141 /// need to explicitly track them to prevent sending them out to peers. Can be called safely 142 /// from any thread. 143 void removeSentTransactions(std::vector<h256> const& _txHashes); 144 145 /// Send new blocks to peers. Should be done after we've verified the PoW but before we've 146 /// imported the blocks into the chain (in order to reduce the uncle rate). Thread-safe (actual 147 /// sending of blocks is done on the network thread). 148 void propagateNewBlocks(std::shared_ptr<VerifiedBlocks const> const& _newBlocks); 149 150 private: 151 static char const* const c_stateNames[static_cast<int>(SyncState::Size)]; 152 static constexpr std::chrono::milliseconds c_backgroundWorkInterval{1000}; 153 154 std::vector<NodeID> selectPeers( 155 std::function<bool(EthereumPeer const&)> const& _predicate) const; 156 157 std::vector<NodeID> randomPeers(std::vector<NodeID> const& _peers, size_t _count) const; 158 159 /// Send top transactions (by nonce and gas price) to available peers 160 void maintainTransactions(); 161 void maintainBlockHashes(h256 const& _currentBlock); 162 void onTransactionImported(ImportResult _ir, h256 const& _h, h512 const& _nodeId); 163 164 /// Initialises the network peer-state, doing the stuff that needs to be once-only. @returns true if it really was first. 165 bool ensureInitialised(); 166 167 void setIdle(NodeID const& _peerID); 168 void setAsking(NodeID const& _peerID, Asking _a); 169 170 /// Are we presently in a critical part of the syncing process with this peer? 171 bool isCriticalSyncing(NodeID const& _peerID) const; 172 173 /// Do we presently need syncing with this peer? 174 bool needsSyncing(NodeID const& _peerID) const; 175 176 std::shared_ptr<p2p::CapabilityHostFace> m_host; 177 178 BlockChain const& m_chain; 179 OverlayDB const& m_db; ///< References to DB, needed for some of the Ethereum Protocol responses. 180 TransactionQueue& m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. 181 BlockQueue& m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). 182 183 u256 m_networkId; 184 185 // We need to keep track of sent blocks and block hashes separately since we propagate new 186 // blocks after we've verified their PoW (and a few other things i.e. they've been imported into 187 // the block queue and verified) but we propagate new block hashes after blocks have been 188 // imported into the chain 189 h256 m_latestBlockHashSent; 190 h256 m_latestBlockSent; 191 h256Hash m_transactionsSent; 192 193 std::atomic<bool> m_newTransactions = {false}; 194 std::atomic<bool> m_newBlocks = {false}; 195 196 std::shared_ptr<BlockChainSync> m_sync; 197 std::atomic<time_t> m_lastTick = { 0 }; 198 199 std::unique_ptr<EthereumHostDataFace> m_hostData; 200 std::unique_ptr<EthereumPeerObserverFace> m_peerObserver; 201 202 std::unordered_map<NodeID, EthereumPeer> m_peers; 203 204 mutable std::mt19937_64 m_urng; // Mersenne Twister psuedo-random number generator 205 206 Logger m_logger{createLogger(VerbosityDebug, "ethcap")}; 207 Logger m_loggerDetail{createLogger(VerbosityTrace, "ethcap")}; 208 Logger m_loggerWarn{createLogger(VerbosityWarning, "ethcap")}; 209 /// Logger for messages about impolite behaivour of peers. 210 Logger m_loggerImpolite{createLogger(VerbosityDebug, "impolite")}; 211 }; 212 213 } 214 } 215