Ethereum  PoC-8
The C++ Implementation of Ethereum
BlockChainSync.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 <mutex>
25 #include <unordered_map>
26 
27 #include <libdevcore/Guards.h>
28 #include <libethcore/Common.h>
29 #include <libethcore/BlockHeader.h>
30 #include <libp2p/Common.h>
31 #include "CommonNet.h"
32 
33 namespace dev
34 {
35 
36 class RLPStream;
37 
38 namespace eth
39 {
40 class EthereumCapability;
41 class BlockQueue;
42 class EthereumPeer;
43 
48 class BlockChainSync final: public HasInvariants
49 {
50 public:
51  explicit BlockChainSync(EthereumCapability& _host);
53  void abortSync();
54 
56  bool isSyncing() const;
57 
59  void restartSync();
60 
63  void completeSync();
64 
66  void onPeerStatus(EthereumPeer const& _peer);
67 
69  void onPeerBlockHeaders(NodeID const& _peerID, RLP const& _r);
70 
72  void onPeerBlockBodies(NodeID const& _peerID, RLP const& _r);
73 
75  void onPeerNewBlock(NodeID const& _peerID, RLP const& _r);
76 
77  void onPeerNewHashes(NodeID const& _peerID, std::vector<std::pair<h256, u256>> const& _hashes);
78 
80  void onPeerAborting();
81 
83  void onBlockImported(BlockHeader const& _info);
84 
86  SyncStatus status() const;
87 
88  static char const* stateName(SyncState _s) { return s_stateNames[static_cast<int>(_s)]; }
89 
90 private:
92  void continueSync();
93 
95  void pauseSync();
96 
97  EthereumCapability& host() { return m_host; }
98  EthereumCapability const& host() const { return m_host; }
99 
100  void resetSync();
101  void syncPeer(NodeID const& _peerID, bool _force);
102  void requestBlocks(NodeID const& _peerID);
103  void clearPeerDownload(NodeID const& _peerID);
104  void clearPeerDownload();
105  void collectBlocks();
106  bool requestDaoForkBlockHeader(NodeID const& _peerID);
107  bool verifyDaoChallengeResponse(RLP const& _r);
108  void logImported(unsigned _success, unsigned _future, unsigned _got, unsigned _unknown);
109 
110 private:
111  struct Header
112  {
113  bytes data;
114  h256 hash;
115  h256 parent;
116  };
117 
119  struct HeaderId
120  {
121  h256 transactionsRoot;
122  h256 uncles;
123 
124  bool operator==(HeaderId const& _other) const
125  {
126  return transactionsRoot == _other.transactionsRoot && uncles == _other.uncles;
127  }
128  };
129 
130  struct HeaderIdHash
131  {
132  std::size_t operator()(const HeaderId& _k) const
133  {
134  size_t seed = 0;
135  h256::hash hasher;
136  boost::hash_combine(seed, hasher(_k.transactionsRoot));
137  boost::hash_combine(seed, hasher(_k.uncles));
138  return seed;
139  }
140  };
141 
142  EthereumCapability& m_host;
143  Handler<> m_bqRoomAvailable;
144  mutable RecursiveMutex x_sync;
146  std::set<NodeID> m_daoChallengedPeers;
147  std::atomic<SyncState> m_state{SyncState::Idle};
148  h256Hash m_knownNewHashes;
149  unsigned m_chainStartBlock = 0;
150  unsigned m_startingBlock = 0;
151  unsigned m_highestBlock = 0;
152  std::unordered_set<unsigned> m_downloadingHeaders;
153  std::unordered_set<unsigned> m_downloadingBodies;
154  std::map<unsigned, std::vector<Header>> m_headers;
155  std::map<unsigned, std::vector<bytes>> m_bodies;
156  std::map<NodeID, std::vector<unsigned>> m_headerSyncPeers;
159  std::map<NodeID, std::vector<unsigned>> m_bodySyncPeers;
160  std::unordered_map<HeaderId, unsigned, HeaderIdHash> m_headerIdToNumber;
161  bool m_haveCommonHeader = false;
162  unsigned m_lastImportedBlock = 0;
163  h256 m_lastImportedBlockHash;
164  u256 m_syncingTotalDifficulty;
165 
166  Logger m_logger{createLogger(VerbosityDebug, "sync")};
167  Logger m_loggerInfo{createLogger(VerbosityInfo, "sync")};
168  Logger m_loggerDetail{createLogger(VerbosityTrace, "sync")};
169 
170 private:
171  static char const* const s_stateNames[static_cast<int>(SyncState::Size)];
172  bool invariants() const override;
173  void logNewBlock(h256 const& _h);
174 };
175 
176 std::ostream& operator<<(std::ostream& _out, SyncStatus const& _sync);
177 
178 }
179 }
void onPeerBlockHeaders(NodeID const &_peerID, RLP const &_r)
Called by peer once it has new block headers during sync.
Inheritable for classes that have invariants.
Definition: Common.h:210
Definition: Address.cpp:20
void restartSync()
Restart sync.
Encapsulation of a block header. Class to contain all of a block header&#39;s data. It is able to parse a...
Definition: BlockHeader.h:96
void onPeerNewHashes(NodeID const &_peerID, std::vector< std::pair< h256, u256 >> const &_hashes)
void abortSync()
Abort all sync activity.
std::ostream & operator<<(std::ostream &_out, BlockHeader const &_bi)
Definition: BlockHeader.h:217
The EthereumCapability class.
Initial chain sync complete. Waiting for new packets.
std::recursive_mutex RecursiveMutex
Definition: Guards.h:38
p2p::NodeID NodeID
Definition: CommonNet.h:105
Must be kept last.
void onPeerBlockBodies(NodeID const &_peerID, RLP const &_r)
Called by peer once it has new block bodies.
Logger createLogger(int _severity, std::string const &_channel)
Definition: Log.h:125
std::vector< byte > bytes
Definition: Common.h:72
FixedHash< 32 > h256
Definition: FixedHash.h:354
SyncStatus status() const
static char const * stateName(SyncState _s)
void onPeerAborting()
Called by peer when it is disconnecting.
Base BlockChain synchronization strategy class. Syncs to peers and keeps up to date. Base class handles blocks downloading but does not contain any details on state transfer logic.
void onPeerStatus(EthereumPeer const &_peer)
Called by peer to report status.
BlockChainSync(EthereumCapability &_host)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Definition: Common.h:121
std::unordered_set< h256 > h256Hash
Definition: FixedHash.h:363
void onBlockImported(BlockHeader const &_info)
Called when a blockchain has imported a new block onto the DB.
Definition: RLP.h:47
boost::log::sources::severity_channel_logger<> Logger
Definition: Log.h:124
void onPeerNewBlock(NodeID const &_peerID, RLP const &_r)
Called by peer once it has new block bodies.