Bitcoin ABC  0.22.12
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 <hash.h>
9 #include <netbase.h>
10 #include <primitives/blockhash.h>
11 #include <seeder/db.h>
12 #include <seeder/messagewriter.h>
13 #include <serialize.h>
14 #include <uint256.h>
15 #include <util/time.h>
16 
17 #include <algorithm>
18 
19 #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL
20 
22  if (sock == INVALID_SOCKET) {
23  return;
24  }
25  if (vSend.empty()) {
26  return;
27  }
28  int nBytes = send(sock, &vSend[0], vSend.size(), 0);
29  if (nBytes > 0) {
30  vSend.erase(vSend.begin(), vSend.begin() + nBytes);
31  } else {
32  close(sock);
34  }
35 }
36 
38  CDataStream &recv) {
39  // tfm::format(std::cout, "%s: RECV %s\n", ToString(you),
40  // strCommand);
41  if (strCommand == NetMsgType::VERSION) {
42  int64_t nTime;
43  CAddress addrMe;
44  CAddress addrFrom;
45  uint64_t nNonce = 1;
46  uint64_t nServiceInt;
47  recv >> nVersion >> nServiceInt >> nTime >> addrMe;
48  you.nServices = ServiceFlags(nServiceInt);
49  recv >> addrFrom >> nNonce;
50  recv >> strSubVer;
51  recv >> nStartingHeight;
52 
56  }
57 
58  if (strCommand == NetMsgType::VERACK) {
60  // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
61  // nVersion);
62  if (vAddr) {
64  std::vector<BlockHash> locatorHash(
65  1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
67  CBlockLocator(locatorHash), uint256());
69  } else {
70  doneAfter = GetTime() + 1;
71  }
73  }
74 
75  if (strCommand == NetMsgType::ADDR && vAddr) {
76  std::vector<CAddress> vAddrNew;
77  recv >> vAddrNew;
78  // tfm::format(std::cout, "%s: got %i addresses\n",
79  // ToString(you),
80  // (int)vAddrNew.size());
81  int64_t now = GetTime();
82  std::vector<CAddress>::iterator it = vAddrNew.begin();
83  if (vAddrNew.size() > 1) {
84  if (doneAfter == 0 || doneAfter > now + 1) {
85  doneAfter = now + 1;
86  }
87  }
88  while (it != vAddrNew.end()) {
89  CAddress &addr = *it;
90  // tfm::format(std::cout, "%s: got address %s\n",
91  // ToString(you),
92  // addr.ToString(), (int)(vAddr->size()));
93  it++;
94  if (addr.nTime <= 100000000 || addr.nTime > now + 600) {
95  addr.nTime = now - 5 * 86400;
96  }
97  if (addr.nTime > now - 604800) {
98  vAddr->push_back(addr);
99  }
100  // tfm::format(std::cout, "%s: added address %s (#%i)\n",
101  // ToString(you),
102  // addr.ToString(), (int)(vAddr->size()));
103  if (vAddr->size() > ADDR_SOFT_CAP) {
104  doneAfter = 1;
106  }
107  }
109  }
110 
112 }
113 
115  if (vRecv.empty()) {
116  return false;
117  }
118 
119  const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
120 
121  do {
122  CDataStream::iterator pstart = std::search(
123  vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
124  uint32_t nHeaderSize =
126  if (vRecv.end() - pstart < nHeaderSize) {
127  if (vRecv.size() > nHeaderSize) {
128  vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
129  }
130  break;
131  }
132  vRecv.erase(vRecv.begin(), pstart);
133  std::vector<char> vHeaderSave(vRecv.begin(),
134  vRecv.begin() + nHeaderSize);
135  CMessageHeader hdr(netMagic);
136  vRecv >> hdr;
137  if (!hdr.IsValidWithoutConfig(netMagic)) {
138  // tfm::format(std::cout, "%s: BAD (invalid header)\n",
139  // ToString(you));
140  ban = 100000;
141  return true;
142  }
143  std::string strCommand = hdr.GetCommand();
144  unsigned int nMessageSize = hdr.nMessageSize;
145  if (nMessageSize > MAX_SIZE) {
146  // tfm::format(std::cout, "%s: BAD (message too large)\n",
147  // ToString(you));
148  ban = 100000;
149  return true;
150  }
151  if (nMessageSize > vRecv.size()) {
152  vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
153  break;
154  }
155  if (vRecv.GetVersion() >= 209) {
156  uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
157  if (memcmp(hash.begin(), hdr.pchChecksum,
159  continue;
160  }
161  }
162  CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize,
164  vRecv.ignore(nMessageSize);
165  if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
166  return true;
167  }
168  // tfm::format(std::cout, "%s: done processing %s\n",
169  // ToString(you),
170  // strCommand);
171  } while (1);
172  return false;
173 }
174 
175 CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
177  nHeaderStart(-1), nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0),
179  if (GetTime() > 1329696000) {
180  vSend.SetVersion(209);
181  vRecv.SetVersion(209);
182  }
183 }
184 
186  // FIXME: This logic is duplicated with CConnman::ConnectNode for no
187  // good reason.
188  bool connected = false;
189  proxyType proxy;
190 
191  if (you.IsValid()) {
192  bool proxyConnectionFailed = false;
193 
194  if (GetProxy(you.GetNetwork(), proxy)) {
195  sock = CreateSocket(proxy.proxy);
196  if (sock == INVALID_SOCKET) {
197  return false;
198  }
199  connected = ConnectThroughProxy(
201  proxyConnectionFailed);
202  } else {
203  // no proxy needed (none set for target network)
204  sock = CreateSocket(you);
205  if (sock == INVALID_SOCKET) {
206  return false;
207  }
208  // no proxy needed (none set for target network)
209  connected =
211  }
212  }
213 
214  if (!connected) {
215  // tfm::format(std::cout, "Cannot connect to %s\n",
216  // ToString(you));
217  CloseSocket(sock);
218  return false;
219  }
220 
221  // Write version message
222  uint64_t nLocalServices = 0;
223  uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
224  CService myService;
225  CAddress me(myService, ServiceFlags(NODE_NETWORK));
226  std::string ver = "/bitcoin-cash-seeder:0.15/";
228  nLocalServices, GetTime(), you, me, nLocalNonce,
229  ver, GetRequireHeight());
230  Send();
231 
232  bool res = true;
233  int64_t now;
234  while (now = GetTime(), ban == 0 && (doneAfter == 0 || doneAfter > now) &&
235  sock != INVALID_SOCKET) {
236  char pchBuf[0x10000];
237  fd_set fdsetRecv;
238  fd_set fdsetError;
239  FD_ZERO(&fdsetRecv);
240  FD_ZERO(&fdsetError);
241  FD_SET(sock, &fdsetRecv);
242  FD_SET(sock, &fdsetError);
243  struct timeval wa;
244  if (doneAfter) {
245  wa.tv_sec = doneAfter - now;
246  wa.tv_usec = 0;
247  } else {
248  wa.tv_sec = GetTimeout();
249  wa.tv_usec = 0;
250  }
251  int ret = select(sock + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
252  if (ret != 1) {
253  if (!doneAfter) {
254  res = false;
255  }
256  break;
257  }
258  int nBytes = recv(sock, pchBuf, sizeof(pchBuf), 0);
259  int nPos = vRecv.size();
260  if (nBytes > 0) {
261  vRecv.resize(nPos + nBytes);
262  memcpy(&vRecv[nPos], pchBuf, nBytes);
263  } else if (nBytes == 0) {
264  // tfm::format(std::cout, "%s: BAD (connection closed
265  // prematurely)\n",
266  // ToString(you));
267  res = false;
268  break;
269  } else {
270  // tfm::format(std::cout, "%s: BAD (connection error)\n",
271  // ToString(you));
272  res = false;
273  break;
274  }
275  ProcessMessages();
276  Send();
277  }
278  if (sock == INVALID_SOCKET) {
279  res = false;
280  }
281  close(sock);
283  return (ban == 0) && res;
284 }
unsigned short GetPort() const
Definition: netaddress.cpp:692
#define BEGIN(a)
Definition: util.h:10
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET &hSocket, int nTimeout, bool manual_connection)
Try to connect to the specified service on the specified socket.
Definition: netbase.cpp:683
vector_type::iterator iterator
Definition: streams.h:212
ServiceFlags
nServices flags.
Definition: protocol.h:320
Describes a place in the block chain to another node such that if the other node doesn&#39;t have the sam...
Definition: block.h:110
int GetVersion() const
Definition: streams.h:386
SOCKET sock
Definition: bitcoin.h:36
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
Definition: protocol.cpp:32
int GetType() const
Definition: streams.h:384
int nStartingHeight
Definition: bitcoin.h:43
void resize(size_type n, value_type c=0)
Definition: streams.h:281
int nVersion
Definition: bitcoin.h:41
void Send()
Definition: bitcoin.cpp:21
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:196
bool empty() const
Definition: streams.h:280
#define INVALID_SOCKET
Definition: compat.h:55
iterator erase(iterator it)
Definition: streams.h:333
enum Network GetNetwork() const
Definition: netaddress.cpp:312
iterator insert(iterator it, const char x=char())
Definition: streams.h:291
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1193
bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, int port, const SOCKET &hSocket, int nTimeout, bool &outProxyConnectionFailed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
Definition: netbase.cpp:856
bool IsValid() const
Definition: netaddress.cpp:244
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:175
CDataStream vSend
Definition: bitcoin.h:37
uint32_t nHeaderStart
Definition: bitcoin.h:39
CAddress you
Definition: bitcoin.h:47
Block-chain checkpoints are compiled-in sanity checks.
Definition: checkpoints.cpp:15
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
Definition: protocol.cpp:28
size_type size() const
Definition: streams.h:279
int64_t doneAfter
Definition: bitcoin.h:46
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:37
void ignore(int nSize)
Definition: streams.h:407
std::string ToStringIP() const
Definition: netaddress.cpp:332
bool Run()
Definition: bitcoin.cpp:185
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:179
A CService with information about it as peer.
Definition: protocol.h:427
bool ProcessMessages()
Definition: bitcoin.cpp:114
static int GetRequireHeight()
Definition: db.h:28
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
Definition: protocol.cpp:23
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:72
#define BITCOIN_SEED_NONCE
Definition: bitcoin.cpp:19
static const uint64_t MAX_SIZE
Definition: serialize.h:26
uint8_t * begin()
Definition: uint256.h:76
static constexpr size_t CHECKSUM_SIZE
Definition: protocol.h:42
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:962
int nConnectTimeout
Definition: netbase.cpp:32
static const unsigned int ADDR_SOFT_CAP
Definition: bitcoin.h:21
int ban
Definition: bitcoin.h:45
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
Definition: protocol.cpp:22
256-bit opaque blob.
Definition: uint256.h:120
unsigned int nTime
Definition: protocol.h:466
ServiceFlags nServices
Definition: protocol.h:463
CService proxy
Definition: netbase.h:37
const_iterator end() const
Definition: streams.h:277
const_iterator begin() const
Definition: streams.h:275
uint32_t nMessageStart
Definition: bitcoin.h:40
CDataStream vRecv
Definition: bitcoin.h:38
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:49
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Definition: protocol.cpp:21
static void WriteMessage(CDataStream &stream, std::string command, Args &&... args)
Definition: messagewriter.h:15
const CChainParams & Params()
Return the currently selected parameters.
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11
PeerMessagingState
Definition: bitcoin.h:23
SOCKET CreateSocket(const CService &addrConnect)
Try to create a socket file descriptor with specific properties in the communications domain (address...
Definition: netbase.cpp:613
std::vector< CAddress > * vAddr
Definition: bitcoin.h:44
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:782
int GetTimeout()
Definition: bitcoin.h:49
void SetVersion(int n)
Definition: streams.h:385
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:27
const CMessageHeader::MessageMagic & NetMagic() const
Definition: chainparams.h:61
std::string strSubVer
Definition: bitcoin.h:42
Message header.
Definition: protocol.h:37
#define END(a)
Definition: util.h:11