Bitcoin ABC  0.24.10
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/time.h>
17 
18 #include <algorithm>
19 
20 #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL
21 
23  if (sock == INVALID_SOCKET) {
24  return;
25  }
26  if (vSend.empty()) {
27  return;
28  }
29  int nBytes = send(sock, &vSend[0], vSend.size(), 0);
30  if (nBytes > 0) {
31  vSend.erase(vSend.begin(), vSend.begin() + nBytes);
32  } else {
33  close(sock);
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  : sock(INVALID_SOCKET), vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0),
178  nHeaderStart(-1), nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0),
179  doneAfter(0), 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 = CreateSocket(proxy.proxy);
197  if (sock == INVALID_SOCKET) {
198  return false;
199  }
200  connected = ConnectThroughProxy(
202  proxyConnectionFailed);
203  } else {
204  // no proxy needed (none set for target network)
205  sock = CreateSocket(you);
206  if (sock == INVALID_SOCKET) {
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  CloseSocket(sock);
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(), ban == 0 && (doneAfter == 0 || doneAfter > now) &&
243  sock != INVALID_SOCKET) {
244  char pchBuf[0x10000];
245  fd_set fdsetRecv;
246  fd_set fdsetError;
247  FD_ZERO(&fdsetRecv);
248  FD_ZERO(&fdsetError);
249  FD_SET(sock, &fdsetRecv);
250  FD_SET(sock, &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 = select(sock + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
260  if (ret != 1) {
261  if (!doneAfter) {
262  res = false;
263  }
264  break;
265  }
266  int nBytes = recv(sock, pchBuf, sizeof(pchBuf), 0);
267  int nPos = vRecv.size();
268  if (nBytes > 0) {
269  vRecv.resize(nPos + nBytes);
270  memcpy(&vRecv[nPos], pchBuf, nBytes);
271  } else if (nBytes == 0) {
272  // tfm::format(std::cout, "%s: BAD (connection closed
273  // prematurely)\n",
274  // ToString(you));
275  res = false;
276  break;
277  } else {
278  // tfm::format(std::cout, "%s: BAD (connection error)\n",
279  // ToString(you));
280  res = false;
281  break;
282  }
283  ProcessMessages();
284  Send();
285  }
286  if (sock == INVALID_SOCKET) {
287  res = false;
288  }
289  close(sock);
291  return (ban == 0) && res;
292 }
GetSerializeSize
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1182
ConnectSocketDirectly
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:696
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:514
CDataStream::insert
iterator insert(iterator it, const char x=char())
Definition: streams.h:292
PeerMessagingState::AwaitingMessages
@ AwaitingMessages
CSeederNode::ban
int ban
Definition: bitcoin.h:46
MessageWriter::WriteMessage
static void WriteMessage(CDataStream &stream, std::string command, Args &&... args)
Definition: messagewriter.h:15
CSeederNode::nStartingHeight
int nStartingHeight
Definition: bitcoin.h:44
CDataStream::begin
const_iterator begin() const
Definition: streams.h:276
CSeederNode::sock
SOCKET sock
Definition: bitcoin.h:37
FormatVersion
std::string FormatVersion(int nVersion)
Definition: clientversion.cpp:47
uint256.h
nConnectTimeout
int nConnectTimeout
Definition: netbase.cpp:35
blockhash.h
GetTime
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:27
clientversion.h
GetRequireHeight
static int GetRequireHeight()
Definition: db.h:28
ServiceFlags
ServiceFlags
nServices flags.
Definition: protocol.h:314
CAddress::nServices
ServiceFlags nServices
Definition: protocol.h:464
NODE_NETWORK
@ NODE_NETWORK
Definition: protocol.h:321
CSeederNode::vRecv
CDataStream vRecv
Definition: bitcoin.h:39
chainparams.h
CSeederNode::you
CAddress you
Definition: bitcoin.h:48
CAddress::nTime
uint32_t nTime
Definition: protocol.h:462
CSeederNode::vSend
CDataStream vSend
Definition: bitcoin.h:38
messagewriter.h
proxyType
Definition: netbase.h:28
CSeederNode::Run
bool Run()
Definition: bitcoin.cpp:186
CSeederNode::Send
void Send()
Definition: bitcoin.cpp:22
CNetAddr::ToStringIP
std::string ToStringIP() const
Definition: netaddress.cpp:540
db.h
SER_NETWORK
@ SER_NETWORK
Definition: serialize.h:165
CDataStream::GetType
int GetType() const
Definition: streams.h:385
CNetAddr::GetNetwork
enum Network GetNetwork() const
Definition: netaddress.cpp:513
Hash
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:74
ADDR_SOFT_CAP
static const unsigned int ADDR_SOFT_CAP
Definition: bitcoin.h:22
CSeederNode::GetTimeout
int GetTimeout()
Definition: bitcoin.h:50
MAX_SIZE
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:30
FormatUserAgent
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.
Definition: clientversion.cpp:66
CSeederNode::ProcessMessage
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:38
NetMsgType::GETHEADERS
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
Definition: protocol.cpp:27
BEGIN
#define BEGIN(a)
Definition: util.h:10
INVALID_SOCKET
#define INVALID_SOCKET
Definition: compat.h:55
CLIENT_NAME
const std::string CLIENT_NAME
Checkpoints
Block-chain checkpoints are compiled-in sanity checks.
Definition: checkpoints.cpp:15
bitcoin.h
send
static RPCHelpMan send()
Definition: rpcwallet.cpp:4730
PeerMessagingState::Finished
@ Finished
CDataStream::end
const_iterator end() const
Definition: streams.h:278
time.h
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:582
CDataStream::erase
iterator erase(iterator it)
Definition: streams.h:334
CNetAddr::IsValid
bool IsValid() const
Definition: netaddress.cpp:441
PeerMessagingState
PeerMessagingState
Definition: bitcoin.h:24
uint256
256-bit opaque blob.
Definition: uint256.h:127
BITCOIN_SEED_NONCE
#define BITCOIN_SEED_NONCE
Definition: bitcoin.cpp:20
ConnectThroughProxy
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:869
base_blob::begin
uint8_t * begin()
Definition: uint256.h:83
CDataStream::size
size_type size() const
Definition: streams.h:280
CService::GetPort
uint16_t GetPort() const
Definition: netaddress.cpp:937
CDataStream::SetVersion
void SetVersion(int n)
Definition: streams.h:386
CMessageHeader::CHECKSUM_SIZE
static constexpr size_t CHECKSUM_SIZE
Definition: protocol.h:42
NetMsgType::ADDR
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
Definition: protocol.cpp:20
CDataStream::ignore
void ignore(int nSize)
Definition: streams.h:408
CLIENT_VERSION
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:44
CSeederNode::nVersion
int nVersion
Definition: bitcoin.h:42
CDataStream::GetVersion
int GetVersion() const
Definition: streams.h:387
CAddress
A CService with information about it as peer.
Definition: protocol.h:421
CMessageHeader
Message header.
Definition: protocol.h:37
CSeederNode::ProcessMessages
bool ProcessMessages()
Definition: bitcoin.cpp:115
CSeederNode::doneAfter
int64_t doneAfter
Definition: bitcoin.h:47
CSeederNode::vAddr
std::vector< CAddress > * vAddr
Definition: bitcoin.h:45
END
#define END(a)
Definition: util.h:11
gArgs
ArgsManager gArgs
Definition: system.cpp:76
CreateSocket
SOCKET CreateSocket(const CService &addrConnect)
Try to create a socket file descriptor with specific properties in the communications domain (address...
Definition: netbase.cpp:626
CDataStream::resize
void resize(size_type n, value_type c=0)
Definition: streams.h:282
CMessageHeader::MessageMagic
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:49
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:508
GetProxy
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:795
serialize.h
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:197
NetMsgType::VERACK
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
Definition: protocol.cpp:19
netbase.h
CDataStream::empty
bool empty() const
Definition: streams.h:281
CSeederNode::strSubVer
std::string strSubVer
Definition: bitcoin.h:43
CBlockLocator
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
NetMsgType::VERSION
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Definition: protocol.cpp:18
CChainParams::NetMagic
const CMessageHeader::MessageMagic & NetMagic() const
Definition: chainparams.h:61
userAgent
std::string userAgent(const Config &config)
Definition: net.cpp:3486
MakeSpan
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
Definition: span.h:229
CSeederNode::CSeederNode
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:176
CDataStream::iterator
vector_type::iterator iterator
Definition: streams.h:213
proxyType::proxy
CService proxy
Definition: netbase.h:37
NetMsgType::GETADDR
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
Definition: protocol.cpp:31
PROTOCOL_VERSION
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11
CloseSocket
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:979