Bitcoin ABC  0.28.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 <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  CService addrMe;
45  uint64_t nNonce = 1;
46  uint64_t nServiceInt;
47  recv >> nVersion >> nServiceInt >> nTime;
48  yourServices = ServiceFlags(nServiceInt);
49  // Ignore the addrMe service bits sent by the peer
50  recv.ignore(8);
51  recv >> addrMe;
52 
53  // The version message includes information about the sending node
54  // which we don't use:
55  // - 8 bytes (service bits)
56  // - 16 bytes (ipv6 address)
57  // - 2 bytes (port)
58  recv.ignore(26);
59  recv >> nNonce;
60  recv >> strSubVer;
61  recv >> nStartingHeight;
62 
66  }
67 
68  if (strCommand == NetMsgType::VERACK) {
70  // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
71  // nVersion);
72  if (vAddr) {
74  std::vector<BlockHash> locatorHash(
75  1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
77  CBlockLocator(locatorHash), uint256());
78  doneAfter = Now<NodeSeconds>() + GetTimeout();
79  } else {
80  doneAfter = Now<NodeSeconds>() + 1s;
81  }
83  }
84 
85  if (strCommand == NetMsgType::ADDR && vAddr) {
86  std::vector<CAddress> vAddrNew;
87  recv >> vAddrNew;
88  // tfm::format(std::cout, "%s: got %i addresses\n",
89  // ToString(you),
90  // (int)vAddrNew.size());
91  auto now = Now<NodeSeconds>();
92  std::vector<CAddress>::iterator it = vAddrNew.begin();
93  if (vAddrNew.size() > 1) {
94  if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
95  doneAfter > now + 1s) {
96  doneAfter = now + 1s;
97  }
98  }
99  while (it != vAddrNew.end()) {
100  CAddress &addr = *it;
101  // tfm::format(std::cout, "%s: got address %s\n",
102  // ToString(you),
103  // addr.ToString(), (int)(vAddr->size()));
104  it++;
105  if (addr.nTime <= NodeSeconds{100000000s} ||
106  addr.nTime > now + 10min) {
107  addr.nTime = now - 5 * 24h;
108  }
109  if (addr.nTime > now - 7 * 24h) {
110  vAddr->push_back(addr);
111  }
112  // tfm::format(std::cout, "%s: added address %s (#%i)\n",
113  // ToString(you),
114  // addr.ToString(), (int)(vAddr->size()));
115  if (vAddr->size() > ADDR_SOFT_CAP) {
116  doneAfter = NodeSeconds{1s};
118  }
119  }
121  }
122 
124 }
125 
127  if (vRecv.empty()) {
128  return false;
129  }
130 
131  const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
132 
133  do {
134  CDataStream::iterator pstart = std::search(
135  vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
136  uint32_t nHeaderSize =
138  if (vRecv.end() - pstart < nHeaderSize) {
139  if (vRecv.size() > nHeaderSize) {
140  vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
141  }
142  break;
143  }
144  vRecv.erase(vRecv.begin(), pstart);
145  std::vector<uint8_t> vHeaderSave(vRecv.begin(),
146  vRecv.begin() + nHeaderSize);
147  CMessageHeader hdr(netMagic);
148  vRecv >> hdr;
149  if (!hdr.IsValidWithoutConfig(netMagic)) {
150  // tfm::format(std::cout, "%s: BAD (invalid header)\n",
151  // ToString(you));
152  ban = 100000;
153  return true;
154  }
155  std::string strCommand = hdr.GetCommand();
156  unsigned int nMessageSize = hdr.nMessageSize;
157  if (nMessageSize > MAX_SIZE) {
158  // tfm::format(std::cout, "%s: BAD (message too large)\n",
159  // ToString(you));
160  ban = 100000;
161  return true;
162  }
163  if (nMessageSize > vRecv.size()) {
164  vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
165  break;
166  }
167  if (vRecv.GetVersion() >= 209) {
168  uint256 hash = Hash(Span{vRecv}.first(nMessageSize));
169  if (memcmp(hash.begin(), hdr.pchChecksum,
171  continue;
172  }
173  }
174  std::vector<uint8_t> vec{vRecv.begin(), vRecv.begin() + nMessageSize};
175  CDataStream vMsg(MakeUCharSpan(vec), vRecv.GetType(),
176  vRecv.GetVersion());
177  vRecv.ignore(nMessageSize);
178  if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
179  return true;
180  }
181  // tfm::format(std::cout, "%s: done processing %s\n",
182  // ToString(you),
183  // strCommand);
184  } while (1);
185  return false;
186 }
187 
188 CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
189  : vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), nHeaderStart(-1),
190  nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0),
191  doneAfter(NodeSeconds{0s}), you(ip),
192  yourServices(ServiceFlags(NODE_NETWORK)) {
193  if (GetTime() > 1329696000) {
194  vSend.SetVersion(209);
195  vRecv.SetVersion(209);
196  }
197 }
198 
200  // FIXME: This logic is duplicated with CConnman::ConnectNode for no
201  // good reason.
202  bool connected = false;
203  proxyType proxy;
204 
205  if (you.IsValid()) {
206  bool proxyConnectionFailed = false;
207 
208  if (GetProxy(you.GetNetwork(), proxy)) {
209  sock = CreateSock(proxy.proxy);
210  if (!sock) {
211  return false;
212  }
213  connected = ConnectThroughProxy(
214  proxy, you.ToStringIP(), you.GetPort(), *sock, nConnectTimeout,
215  proxyConnectionFailed);
216  } else {
217  // no proxy needed (none set for target network)
218  sock = CreateSock(you);
219  if (!sock) {
220  return false;
221  }
222  // no proxy needed (none set for target network)
223  connected =
225  }
226  }
227 
228  if (!connected) {
229  // tfm::format(std::cout, "Cannot connect to %s\n",
230  // ToString(you));
231  sock.reset();
232  return false;
233  }
234 
235  // Write version message
236  // Don't include the time in CAddress serialization. See D14753.
237  uint64_t nLocalServices = 0;
238  uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
239  uint64_t your_services{yourServices};
240  uint64_t my_services{ServiceFlags(NODE_NETWORK)};
241  uint8_t fRelayTxs = 0;
242 
243  const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
244  const std::string clientVersion =
245  gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
246  const std::string userAgent =
247  FormatUserAgent(clientName, clientVersion, {"seeder"});
248 
250  nLocalServices, GetTime(), your_services, you,
251  my_services, CService(), nLocalNonce, userAgent,
252  GetRequireHeight(), fRelayTxs);
253  Send();
254 
255  bool res = true;
256  NodeSeconds now;
257  while (now = Now<NodeSeconds>(),
258  ban == 0 &&
259  (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
260  doneAfter > now) &&
261  sock) {
262  char pchBuf[0x10000];
263  fd_set fdsetRecv;
264  fd_set fdsetError;
265  FD_ZERO(&fdsetRecv);
266  FD_ZERO(&fdsetError);
267  FD_SET(sock->Get(), &fdsetRecv);
268  FD_SET(sock->Get(), &fdsetError);
269  struct timeval wa;
270  if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) != 0) {
271  wa.tv_sec = (doneAfter - now).count();
272  wa.tv_usec = 0;
273  } else {
274  wa.tv_sec = GetTimeout().count();
275  wa.tv_usec = 0;
276  }
277  int ret =
278  select(sock->Get() + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
279  if (ret != 1) {
280  if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0) {
281  res = false;
282  }
283  break;
284  }
285  int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
286  int nPos = vRecv.size();
287  if (nBytes > 0) {
288  vRecv.resize(nPos + nBytes);
289  memcpy(&vRecv[nPos], pchBuf, nBytes);
290  } else if (nBytes == 0) {
291  // tfm::format(std::cout, "%s: BAD (connection closed
292  // prematurely)\n",
293  // ToString(you));
294  res = false;
295  break;
296  } else {
297  // tfm::format(std::cout, "%s: BAD (connection error)\n",
298  // ToString(you));
299  res = false;
300  break;
301  }
302  ProcessMessages();
303  Send();
304  }
305  if (!sock) {
306  res = false;
307  }
308  sock.reset();
309  return (ban == 0) && res;
310 }
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:603
A CService with information about it as peer.
Definition: protocol.h:442
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
Definition: protocol.h:544
const CMessageHeader::MessageMagic & NetMagic() const
Definition: chainparams.h:88
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:199
const_iterator begin() const
Definition: streams.h:242
void SetVersion(int n)
Definition: streams.h:355
iterator insert(iterator it, const uint8_t x)
Definition: streams.h:258
int GetType() const
Definition: streams.h:354
int GetVersion() const
Definition: streams.h:356
const_iterator end() const
Definition: streams.h:244
void ignore(int nSize)
Definition: streams.h:377
void resize(size_type n, value_type c=0)
Definition: streams.h:248
bool empty() const
Definition: streams.h:247
vector_type::iterator iterator
Definition: streams.h:215
iterator erase(iterator it)
Definition: streams.h:298
size_type size() const
Definition: streams.h:246
Message header.
Definition: protocol.h:34
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:39
uint8_t pchChecksum[CHECKSUM_SIZE]
Definition: protocol.h:72
std::string GetCommand() const
Definition: protocol.cpp:115
uint32_t nMessageSize
Definition: protocol.h:71
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:46
std::string ToStringIP() const
Definition: netaddress.cpp:628
bool IsValid() const
Definition: netaddress.cpp:479
enum Network GetNetwork() const
Definition: netaddress.cpp:551
CDataStream vRecv
Definition: bitcoin.h:43
CService you
Definition: bitcoin.h:52
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:188
CDataStream vSend
Definition: bitcoin.h:42
bool Run()
Definition: bitcoin.cpp:199
int nStartingHeight
Definition: bitcoin.h:48
int nVersion
Definition: bitcoin.h:46
std::vector< CAddress > * vAddr
Definition: bitcoin.h:49
ServiceFlags yourServices
Definition: bitcoin.h:53
bool ProcessMessages()
Definition: bitcoin.cpp:126
std::string strSubVer
Definition: bitcoin.h:47
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:38
void Send()
Definition: bitcoin.cpp:23
std::chrono::seconds GetTimeout()
Definition: bitcoin.h:55
int ban
Definition: bitcoin.h:50
NodeSeconds doneAfter
Definition: bitcoin.h:51
std::unique_ptr< Sock > sock
Definition: bitcoin.h:41
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:545
uint16_t GetPort() const
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:93
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:74
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:3591
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:335
@ NODE_NETWORK
Definition: protocol.h:342
#define BITCOIN_SEED_NONCE
Definition: bitcoin.cpp:21
PeerMessagingState
Definition: bitcoin.h:26
static const unsigned int ADDR_SOFT_CAP
Definition: bitcoin.h:24
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:1276
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) uint8_t member types only.
Definition: span.h:307
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:105
ArgsManager gArgs
Definition: system.cpp:80
static int count
Definition: tests.c:31
int64_t GetTime()
Definition: time.cpp:109
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition: time.h:25
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11