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 <common/args.h>
10 #include <hash.h>
11 #include <netbase.h>
12 #include <primitives/blockhash.h>
13 #include <seeder/db.h>
14 #include <seeder/messagewriter.h>
15 #include <serialize.h>
16 #include <uint256.h>
17 #include <util/sock.h>
18 #include <util/time.h>
19 
20 #include <algorithm>
21 
22 #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL
23 
25  if (!sock) {
26  return;
27  }
28  if (vSend.empty()) {
29  return;
30  }
31  int nBytes = sock->Send(&vSend[0], vSend.size(), 0);
32  if (nBytes > 0) {
33  vSend.erase(vSend.begin(), vSend.begin() + nBytes);
34  } else {
35  sock.reset();
36  }
37 }
38 
40  CDataStream &recv) {
41  // tfm::format(std::cout, "%s: RECV %s\n", ToString(you),
42  // strCommand);
43  if (strCommand == NetMsgType::VERSION) {
44  int64_t nTime;
45  CService addrMe;
46  uint64_t nNonce = 1;
47  uint64_t nServiceInt;
48  recv >> nVersion >> nServiceInt >> nTime;
49  yourServices = ServiceFlags(nServiceInt);
50  // Ignore the addrMe service bits sent by the peer
51  recv.ignore(8);
52  recv >> addrMe;
53 
54  // The version message includes information about the sending node
55  // which we don't use:
56  // - 8 bytes (service bits)
57  // - 16 bytes (ipv6 address)
58  // - 2 bytes (port)
59  recv.ignore(26);
60  recv >> nNonce;
61  recv >> strSubVer;
62  recv >> nStartingHeight;
63 
67  }
68 
69  if (strCommand == NetMsgType::VERACK) {
71  // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
72  // nVersion);
73  if (vAddr) {
75  std::vector<BlockHash> locatorHash(
76  1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
78  CBlockLocator(locatorHash), uint256());
79  doneAfter = Now<NodeSeconds>() + GetTimeout();
80  } else {
81  doneAfter = Now<NodeSeconds>() + 1s;
82  }
84  }
85 
86  if (strCommand == NetMsgType::ADDR && vAddr) {
87  std::vector<CAddress> vAddrNew;
88  recv >> vAddrNew;
89  // tfm::format(std::cout, "%s: got %i addresses\n",
90  // ToString(you),
91  // (int)vAddrNew.size());
92  auto now = Now<NodeSeconds>();
93  std::vector<CAddress>::iterator it = vAddrNew.begin();
94  if (vAddrNew.size() > 1) {
95  if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
96  doneAfter > now + 1s) {
97  doneAfter = now + 1s;
98  }
99  }
100  while (it != vAddrNew.end()) {
101  CAddress &addr = *it;
102  // tfm::format(std::cout, "%s: got address %s\n",
103  // ToString(you),
104  // addr.ToString(), (int)(vAddr->size()));
105  it++;
106  if (addr.nTime <= NodeSeconds{100000000s} ||
107  addr.nTime > now + 10min) {
108  addr.nTime = now - 5 * 24h;
109  }
110  if (addr.nTime > now - 7 * 24h) {
111  vAddr->push_back(addr);
112  }
113  // tfm::format(std::cout, "%s: added address %s (#%i)\n",
114  // ToString(you),
115  // addr.ToString(), (int)(vAddr->size()));
116  if (vAddr->size() > ADDR_SOFT_CAP) {
117  doneAfter = NodeSeconds{1s};
119  }
120  }
122  }
123 
125 }
126 
128  if (vRecv.empty()) {
129  return false;
130  }
131 
132  const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
133 
134  do {
135  CDataStream::iterator pstart = std::search(
136  vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
137  uint32_t nHeaderSize =
139  if (vRecv.end() - pstart < nHeaderSize) {
140  if (vRecv.size() > nHeaderSize) {
141  vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
142  }
143  break;
144  }
145  vRecv.erase(vRecv.begin(), pstart);
146  std::vector<std::byte> vHeaderSave(vRecv.begin(),
147  vRecv.begin() + nHeaderSize);
148  CMessageHeader hdr(netMagic);
149  vRecv >> hdr;
150  if (!hdr.IsValidWithoutConfig(netMagic)) {
151  // tfm::format(std::cout, "%s: BAD (invalid header)\n",
152  // ToString(you));
153  ban = 100000;
154  return true;
155  }
156  std::string strCommand = hdr.GetCommand();
157  unsigned int nMessageSize = hdr.nMessageSize;
158  if (nMessageSize > MAX_SIZE) {
159  // tfm::format(std::cout, "%s: BAD (message too large)\n",
160  // ToString(you));
161  ban = 100000;
162  return true;
163  }
164  if (nMessageSize > vRecv.size()) {
165  vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
166  break;
167  }
168  if (vRecv.GetVersion() >= 209) {
169  uint256 hash = Hash(Span{vRecv}.first(nMessageSize));
170  if (memcmp(hash.begin(), hdr.pchChecksum,
172  continue;
173  }
174  }
175  std::vector<std::byte> vec{vRecv.begin(), vRecv.begin() + nMessageSize};
176  CDataStream vMsg(MakeUCharSpan(vec), vRecv.GetType(),
177  vRecv.GetVersion());
178  vRecv.ignore(nMessageSize);
179  if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
180  return true;
181  }
182  // tfm::format(std::cout, "%s: done processing %s\n",
183  // ToString(you),
184  // strCommand);
185  } while (1);
186  return false;
187 }
188 
189 CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
190  : vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), nHeaderStart(-1),
191  nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0),
192  doneAfter(NodeSeconds{0s}), you(ip),
193  yourServices(ServiceFlags(NODE_NETWORK)) {
194  if (GetTime() > 1329696000) {
195  vSend.SetVersion(209);
196  vRecv.SetVersion(209);
197  }
198 }
199 
201  // FIXME: This logic is duplicated with CConnman::ConnectNode for no
202  // good reason.
203  bool connected = false;
204  proxyType proxy;
205 
206  if (you.IsValid()) {
207  bool proxyConnectionFailed = false;
208 
209  if (GetProxy(you.GetNetwork(), proxy)) {
210  sock = CreateSock(proxy.proxy);
211  if (!sock) {
212  return false;
213  }
214  connected = ConnectThroughProxy(
215  proxy, you.ToStringIP(), you.GetPort(), *sock, nConnectTimeout,
216  proxyConnectionFailed);
217  } else {
218  // no proxy needed (none set for target network)
219  sock = CreateSock(you);
220  if (!sock) {
221  return false;
222  }
223  // no proxy needed (none set for target network)
224  connected =
226  }
227  }
228 
229  if (!connected) {
230  // tfm::format(std::cout, "Cannot connect to %s\n",
231  // ToString(you));
232  sock.reset();
233  return false;
234  }
235 
236  // Write version message
237  // Don't include the time in CAddress serialization. See D14753.
238  uint64_t nLocalServices = 0;
239  uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
240  uint64_t your_services{yourServices};
241  uint64_t my_services{ServiceFlags(NODE_NETWORK)};
242  uint8_t fRelayTxs = 0;
243 
244  const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
245  const std::string clientVersion =
246  gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
247  const std::string userAgent =
248  FormatUserAgent(clientName, clientVersion, {"seeder"});
249 
251  nLocalServices, GetTime(), your_services, you,
252  my_services, CService(), nLocalNonce, userAgent,
253  GetRequireHeight(), fRelayTxs);
254  Send();
255 
256  bool res = true;
257  NodeSeconds now;
258  while (now = Now<NodeSeconds>(),
259  ban == 0 &&
260  (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
261  doneAfter > now) &&
262  sock) {
263  char pchBuf[0x10000];
264  fd_set fdsetRecv;
265  fd_set fdsetError;
266  FD_ZERO(&fdsetRecv);
267  FD_ZERO(&fdsetError);
268  FD_SET(sock->Get(), &fdsetRecv);
269  FD_SET(sock->Get(), &fdsetError);
270  struct timeval wa;
271  if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) != 0) {
272  wa.tv_sec = (doneAfter - now).count();
273  wa.tv_usec = 0;
274  } else {
275  wa.tv_sec = GetTimeout().count();
276  wa.tv_usec = 0;
277  }
278  int ret =
279  select(sock->Get() + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
280  if (ret != 1) {
281  if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0) {
282  res = false;
283  }
284  break;
285  }
286  int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
287  int nPos = vRecv.size();
288  if (nBytes > 0) {
289  vRecv.resize(nPos + nBytes);
290  memcpy(&vRecv[nPos], pchBuf, nBytes);
291  } else if (nBytes == 0) {
292  // tfm::format(std::cout, "%s: BAD (connection closed
293  // prematurely)\n",
294  // ToString(you));
295  res = false;
296  break;
297  } else {
298  // tfm::format(std::cout, "%s: BAD (connection error)\n",
299  // ToString(you));
300  res = false;
301  break;
302  }
303  ProcessMessages();
304  Send();
305  }
306  if (!sock) {
307  res = false;
308  }
309  sock.reset();
310  return (ban == 0) && res;
311 }
ArgsManager gArgs
Definition: args.cpp:38
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:19
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:494
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:94
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:177
const_iterator begin() const
Definition: streams.h:219
void SetVersion(int n)
Definition: streams.h:338
int GetType() const
Definition: streams.h:337
int GetVersion() const
Definition: streams.h:339
iterator insert(iterator it, const value_type x)
Definition: streams.h:237
const_iterator end() const
Definition: streams.h:221
void ignore(int nSize)
Definition: streams.h:360
bool empty() const
Definition: streams.h:224
vector_type::iterator iterator
Definition: streams.h:193
void resize(size_type n, value_type c=value_type{})
Definition: streams.h:225
iterator erase(iterator it)
Definition: streams.h:281
size_type size() const
Definition: streams.h:223
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:175
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:116
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:189
CDataStream vSend
Definition: bitcoin.h:42
bool Run()
Definition: bitcoin.cpp:200
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:127
std::string strSubVer
Definition: bitcoin.h:47
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:39
void Send()
Definition: bitcoin.cpp:24
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:85
CService proxy
Definition: netbase.h:40
256-bit opaque blob.
Definition: uint256.h:129
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:31
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
Definition: protocol.cpp:20
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Definition: protocol.cpp:18
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
Definition: protocol.cpp:27
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
Definition: protocol.cpp:19
std::string userAgent(const Config &config)
Definition: net.cpp:3592
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:22
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:10
#define END(a)
Definition: util.h:11
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:152
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1258
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:337
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
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