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'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....
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.