Bitcoin ABC  0.26.3
P2P Digital Currency
bitcoin.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2020 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <seeder/bitcoin.h>
6 
7 #include <chainparams.h>
8 #include <clientversion.h>
9 #include <hash.h>
10 #include <netbase.h>
11 #include <primitives/blockhash.h>
12 #include <seeder/db.h>
13 #include <seeder/messagewriter.h>
14 #include <serialize.h>
15 #include <uint256.h>
16 #include <util/sock.h>
17 #include <util/time.h>
18 
19 #include <algorithm>
20 
21 #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL
22 
24  if (!sock) {
25  return;
26  }
27  if (vSend.empty()) {
28  return;
29  }
30  int nBytes = sock->Send(&vSend[0], vSend.size(), 0);
31  if (nBytes > 0) {
32  vSend.erase(vSend.begin(), vSend.begin() + nBytes);
33  } else {
34  sock.reset();
35  }
36 }
37 
39  CDataStream &recv) {
40  // tfm::format(std::cout, "%s: RECV %s\n", ToString(you),
41  // strCommand);
42  if (strCommand == NetMsgType::VERSION) {
43  int64_t nTime;
44  CAddress addrMe;
45  CAddress addrFrom;
46  uint64_t nNonce = 1;
47  uint64_t nServiceInt;
48  recv >> nVersion >> nServiceInt >> nTime >> addrMe;
49  you.nServices = ServiceFlags(nServiceInt);
50  recv >> addrFrom >> nNonce;
51  recv >> strSubVer;
52  recv >> nStartingHeight;
53 
57  }
58 
59  if (strCommand == NetMsgType::VERACK) {
61  // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
62  // nVersion);
63  if (vAddr) {
65  std::vector<BlockHash> locatorHash(
66  1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
68  CBlockLocator(locatorHash), uint256());
70  } else {
71  doneAfter = GetTime() + 1;
72  }
74  }
75 
76  if (strCommand == NetMsgType::ADDR && vAddr) {
77  std::vector<CAddress> vAddrNew;
78  recv >> vAddrNew;
79  // tfm::format(std::cout, "%s: got %i addresses\n",
80  // ToString(you),
81  // (int)vAddrNew.size());
82  int64_t now = GetTime();
83  std::vector<CAddress>::iterator it = vAddrNew.begin();
84  if (vAddrNew.size() > 1) {
85  if (doneAfter == 0 || doneAfter > now + 1) {
86  doneAfter = now + 1;
87  }
88  }
89  while (it != vAddrNew.end()) {
90  CAddress &addr = *it;
91  // tfm::format(std::cout, "%s: got address %s\n",
92  // ToString(you),
93  // addr.ToString(), (int)(vAddr->size()));
94  it++;
95  if (addr.nTime <= 100000000 || addr.nTime > now + 600) {
96  addr.nTime = now - 5 * 86400;
97  }
98  if (addr.nTime > now - 604800) {
99  vAddr->push_back(addr);
100  }
101  // tfm::format(std::cout, "%s: added address %s (#%i)\n",
102  // ToString(you),
103  // addr.ToString(), (int)(vAddr->size()));
104  if (vAddr->size() > ADDR_SOFT_CAP) {
105  doneAfter = 1;
107  }
108  }
110  }
111 
113 }
114 
116  if (vRecv.empty()) {
117  return false;
118  }
119 
120  const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
121 
122  do {
123  CDataStream::iterator pstart = std::search(
124  vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
125  uint32_t nHeaderSize =
127  if (vRecv.end() - pstart < nHeaderSize) {
128  if (vRecv.size() > nHeaderSize) {
129  vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
130  }
131  break;
132  }
133  vRecv.erase(vRecv.begin(), pstart);
134  std::vector<char> vHeaderSave(vRecv.begin(),
135  vRecv.begin() + nHeaderSize);
136  CMessageHeader hdr(netMagic);
137  vRecv >> hdr;
138  if (!hdr.IsValidWithoutConfig(netMagic)) {
139  // tfm::format(std::cout, "%s: BAD (invalid header)\n",
140  // ToString(you));
141  ban = 100000;
142  return true;
143  }
144  std::string strCommand = hdr.GetCommand();
145  unsigned int nMessageSize = hdr.nMessageSize;
146  if (nMessageSize > MAX_SIZE) {
147  // tfm::format(std::cout, "%s: BAD (message too large)\n",
148  // ToString(you));
149  ban = 100000;
150  return true;
151  }
152  if (nMessageSize > vRecv.size()) {
153  vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
154  break;
155  }
156  if (vRecv.GetVersion() >= 209) {
157  uint256 hash = Hash(MakeSpan(vRecv).first(nMessageSize));
158  if (memcmp(hash.begin(), hdr.pchChecksum,
160  continue;
161  }
162  }
163  CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize,
165  vRecv.ignore(nMessageSize);
166  if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
167  return true;
168  }
169  // tfm::format(std::cout, "%s: done processing %s\n",
170  // ToString(you),
171  // strCommand);
172  } while (1);
173  return false;
174 }
175 
176 CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
177  : vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), nHeaderStart(-1),
178  nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0), doneAfter(0),
179  you(ip, ServiceFlags(NODE_NETWORK)) {
180  if (GetTime() > 1329696000) {
181  vSend.SetVersion(209);
182  vRecv.SetVersion(209);
183  }
184 }
185 
187  // FIXME: This logic is duplicated with CConnman::ConnectNode for no
188  // good reason.
189  bool connected = false;
190  proxyType proxy;
191 
192  if (you.IsValid()) {
193  bool proxyConnectionFailed = false;
194 
195  if (GetProxy(you.GetNetwork(), proxy)) {
196  sock = CreateSock(proxy.proxy);
197  if (!sock) {
198  return false;
199  }
200  connected = ConnectThroughProxy(
201  proxy, you.ToStringIP(), you.GetPort(), *sock, nConnectTimeout,
202  proxyConnectionFailed);
203  } else {
204  // no proxy needed (none set for target network)
205  sock = CreateSock(you);
206  if (!sock) {
207  return false;
208  }
209  // no proxy needed (none set for target network)
210  connected =
212  }
213  }
214 
215  if (!connected) {
216  // tfm::format(std::cout, "Cannot connect to %s\n",
217  // ToString(you));
218  sock.reset();
219  return false;
220  }
221 
222  // Write version message
223  uint64_t nLocalServices = 0;
224  uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
225  CService myService;
226  CAddress me(myService, ServiceFlags(NODE_NETWORK));
227  uint8_t fRelayTxs = 0;
228 
229  const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
230  const std::string clientVersion =
231  gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
232  const std::string userAgent =
233  FormatUserAgent(clientName, clientVersion, {"seeder"});
234 
236  nLocalServices, GetTime(), you, me, nLocalNonce,
237  userAgent, GetRequireHeight(), fRelayTxs);
238  Send();
239 
240  bool res = true;
241  int64_t now;
242  while (now = GetTime(),
243  ban == 0 && (doneAfter == 0 || doneAfter > now) && sock) {
244  char pchBuf[0x10000];
245  fd_set fdsetRecv;
246  fd_set fdsetError;
247  FD_ZERO(&fdsetRecv);
248  FD_ZERO(&fdsetError);
249  FD_SET(sock->Get(), &fdsetRecv);
250  FD_SET(sock->Get(), &fdsetError);
251  struct timeval wa;
252  if (doneAfter) {
253  wa.tv_sec = doneAfter - now;
254  wa.tv_usec = 0;
255  } else {
256  wa.tv_sec = GetTimeout();
257  wa.tv_usec = 0;
258  }
259  int ret =
260  select(sock->Get() + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
261  if (ret != 1) {
262  if (!doneAfter) {
263  res = false;
264  }
265  break;
266  }
267  int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
268  int nPos = vRecv.size();
269  if (nBytes > 0) {
270  vRecv.resize(nPos + nBytes);
271  memcpy(&vRecv[nPos], pchBuf, nBytes);
272  } else if (nBytes == 0) {
273  // tfm::format(std::cout, "%s: BAD (connection closed
274  // prematurely)\n",
275  // ToString(you));
276  res = false;
277  break;
278  } else {
279  // tfm::format(std::cout, "%s: BAD (connection error)\n",
280  // ToString(you));
281  res = false;
282  break;
283  }
284  ProcessMessages();
285  Send();
286  }
287  if (!sock) {
288  res = false;
289  }
290  sock.reset();
291  return (ban == 0) && res;
292 }
const CChainParams & Params()
Return the currently selected parameters.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:584
A CService with information about it as peer.
Definition: protocol.h:445
ServiceFlags nServices
Definition: protocol.h:488
uint32_t nTime
Definition: protocol.h:486
const CMessageHeader::MessageMagic & NetMagic() const
Definition: chainparams.h:88
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:197
const_iterator begin() const
Definition: streams.h:276
void SetVersion(int n)
Definition: streams.h:386
int GetType() const
Definition: streams.h:385
int GetVersion() const
Definition: streams.h:387
const_iterator end() const
Definition: streams.h:278
void ignore(int nSize)
Definition: streams.h:408
void resize(size_type n, value_type c=0)
Definition: streams.h:282
bool empty() const
Definition: streams.h:281
vector_type::iterator iterator
Definition: streams.h:213
iterator erase(iterator it)
Definition: streams.h:334
size_type size() const
Definition: streams.h:280
iterator insert(iterator it, const char x=char())
Definition: streams.h:292
Message header.
Definition: protocol.h:37
bool IsValidWithoutConfig(const MessageMagic &magic) const
This is a transition method in order to stay compatible with older code that do not use the config.
Definition: protocol.cpp:174
static constexpr size_t CHECKSUM_SIZE
Definition: protocol.h:42
uint8_t pchChecksum[CHECKSUM_SIZE]
Definition: protocol.h:75
std::string GetCommand() const
Definition: protocol.cpp:115
uint32_t nMessageSize
Definition: protocol.h:74
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:49
std::string ToStringIP() const
Definition: netaddress.cpp:578
bool IsValid() const
Definition: netaddress.cpp:479
enum Network GetNetwork() const
Definition: netaddress.cpp:551
CDataStream vRecv
Definition: bitcoin.h:41
CAddress you
Definition: bitcoin.h:50
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:176
CDataStream vSend
Definition: bitcoin.h:40
bool Run()
Definition: bitcoin.cpp:186
int nStartingHeight
Definition: bitcoin.h:46
int nVersion
Definition: bitcoin.h:44
std::vector< CAddress > * vAddr
Definition: bitcoin.h:47
bool ProcessMessages()
Definition: bitcoin.cpp:115
std::string strSubVer
Definition: bitcoin.h:45
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:38
void Send()
Definition: bitcoin.cpp:23
int GetTimeout()
Definition: bitcoin.h:52
int ban
Definition: bitcoin.h:48
std::unique_ptr< Sock > sock
Definition: bitcoin.h:39
int64_t doneAfter
Definition: bitcoin.h:49
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:545
uint16_t GetPort() const
Definition: netaddress.cpp:975
uint8_t * begin()
Definition: uint256.h:83
CService proxy
Definition: netbase.h:40
256-bit opaque blob.
Definition: uint256.h:127
std::string FormatVersion(int nVersion)
std::string FormatUserAgent(const std::string &name, const std::string &version, const std::vector< std::string > &comments)
Format the subversion field according to BIP 14 spec.
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
const std::string CLIENT_NAME
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:75
Block-chain checkpoints are compiled-in sanity checks.
Definition: checkpoints.cpp:9
static void WriteMessage(CDataStream &stream, std::string command, Args &&...args)
Definition: messagewriter.h:15
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
Definition: protocol.cpp:30
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
Definition: protocol.cpp:19
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Definition: protocol.cpp:17
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
Definition: protocol.cpp:26
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
Definition: protocol.cpp:18
std::string userAgent(const Config &config)
Definition: net.cpp:3609
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:720
bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, uint16_t port, const Sock &sock, int nTimeout, bool &outProxyConnectionFailed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
Definition: netbase.cpp:763
bool ConnectSocketDirectly(const CService &addrConnect, const Sock &sock, int nTimeout, bool manual_connection)
Try to connect to the specified service on the specified socket.
Definition: netbase.cpp:634
std::function< std::unique_ptr< Sock >const CService &)> CreateSock
Socket factory.
Definition: netbase.cpp:620
int nConnectTimeout
Definition: netbase.cpp:37
ServiceFlags
nServices flags.
Definition: protocol.h:338
@ NODE_NETWORK
Definition: protocol.h:345
#define BITCOIN_SEED_NONCE
Definition: bitcoin.cpp:21
PeerMessagingState
Definition: bitcoin.h:24
static const unsigned int ADDR_SOFT_CAP
Definition: bitcoin.h:22
static int GetRequireHeight()
Definition: db.h:28
#define BEGIN(a)
Definition: util.h:8
#define END(a)
Definition: util.h:9
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
Definition: serialize.h:31
@ SER_NETWORK
Definition: serialize.h:166
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1259
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
Definition: span.h:259
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:100
ArgsManager gArgs
Definition: system.cpp:77
T GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:71
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11