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