Bitcoin ABC 0.30.7
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 <net_processing.h>
12#include <netbase.h>
14#include <seeder/db.h>
16#include <serialize.h>
17#include <uint256.h>
18#include <util/sock.h>
19#include <util/time.h>
20#include <validation.h>
21
22#include <algorithm>
23
24#define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL
25
27 if (!sock) {
28 return;
29 }
30 if (vSend.empty()) {
31 return;
32 }
33 int nBytes = sock->Send(&vSend[0], vSend.size(), 0);
34 if (nBytes > 0) {
35 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
36 } else {
37 sock.reset();
38 }
39}
40
42 CDataStream &recv) {
43 // tfm::format(std::cout, "%s: RECV %s\n", ToString(you),
44 // strCommand);
45 if (strCommand == NetMsgType::VERSION) {
46 int64_t nTime;
47 CService addrMe;
48 uint64_t nNonce = 1;
49 uint64_t nServiceInt;
50 recv >> nVersion >> nServiceInt >> nTime;
51 yourServices = ServiceFlags(nServiceInt);
52 // Ignore the addrMe service bits sent by the peer
53 recv.ignore(8);
54 recv >> addrMe;
55
56 // The version message includes information about the sending node
57 // which we don't use:
58 // - 8 bytes (service bits)
59 // - 16 bytes (ipv6 address)
60 // - 2 bytes (port)
61 recv.ignore(26);
62 recv >> nNonce;
63 recv >> strSubVer;
64 recv >> nStartingHeight;
65
69 }
70
71 if (strCommand == NetMsgType::VERACK) {
73 // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
74 // nVersion);
75 auto doneAfterDelta{1s};
76 // Note in the current codebase: vAddr is non-nullptr only once per day
77 // for each node we check
78 if (vAddr) {
80 doneAfterDelta = GetTimeout();
81 needAddrReply = true;
82 }
83
84 // request headers starting after last checkpoint (only if we have
85 // checkpoints for this network)
86 if (HasCheckpoint()) {
87 std::vector<BlockHash> locatorHash(
88 1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
90 CBlockLocator(std::move(locatorHash)),
91 uint256());
92 }
93 doneAfter = Now<NodeSeconds>() + doneAfterDelta;
95 }
96
97 if (strCommand == NetMsgType::ADDR && vAddr) {
98 needAddrReply = false;
99 std::vector<CAddress> vAddrNew;
100 recv >> vAddrNew;
101 // tfm::format(std::cout, "%s: got %i addresses\n",
102 // ToString(you),
103 // (int)vAddrNew.size());
104 auto now = Now<NodeSeconds>();
105 std::vector<CAddress>::iterator it = vAddrNew.begin();
106 if (vAddrNew.size() > 1) {
107 if (checkpointVerified &&
108 (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
109 doneAfter > now + 1s)) {
110 doneAfter = now + 1s;
111 }
112 }
113 while (it != vAddrNew.end()) {
114 CAddress &addr = *it;
115 // tfm::format(std::cout, "%s: got address %s\n",
116 // ToString(you),
117 // addr.ToString(), (int)(vAddr->size()));
118 it++;
119 if (addr.nTime <= NodeSeconds{100000000s} ||
120 addr.nTime > now + 10min) {
121 addr.nTime = now - 5 * 24h;
122 }
123 if (addr.nTime > now - 7 * 24h) {
124 vAddr->push_back(addr);
125 }
126 // tfm::format(std::cout, "%s: added address %s (#%i)\n",
127 // ToString(you),
128 // addr.ToString(), (int)(vAddr->size()));
129 if (vAddr->size() > ADDR_SOFT_CAP) {
130 if (!checkpointVerified) {
131 // stop processing addresses now since we hit the soft cap,
132 // but we will continue to await headers
133 break;
134 }
135 // stop processing addresses and since we aren't waiting for
136 // headers, stop processing immediately
137 doneAfter = now;
139 }
140 }
142 }
143
144 if (strCommand == NetMsgType::HEADERS) {
145 uint64_t nCount = ReadCompactSize(recv);
146 if (nCount == 0) {
147 // Empty HEADERS messages can be sent when the peer does not have
148 // enough chainwork.
150 }
151 if (nCount > MAX_HEADERS_RESULTS) {
152 ban = 100000;
154 }
155
156 CBlockHeader header;
157 recv >> header;
158
159 // If the peer has a chain longer than our last checkpoint, we expect
160 // that the first header it will send will be the one just after
161 // that checkpoint, as we claim to have the checkpoint as our starting
162 // height in the version message.
164 if (header.hashPrevBlock !=
165 Params().Checkpoints().mapCheckpoints.rbegin()->second) {
166 // This node is synced higher than the last checkpoint height
167 // but does not have the checkpoint block in its chain.
168 // This means it must be on the wrong chain. We treat these
169 // nodes the same as nodes with the wrong net magic.
170 // std::fprintf(stdout, "%s: BAD \"%s\" (wrong chain)\n",
171 // ToString(you).c_str(), strSubVer.c_str());
172 ban = 100000;
174 }
175 checkpointVerified = true;
176 if (!needAddrReply) {
177 // we are no longer waiting for headers or addr, so we can
178 // stop processing this node
179 doneAfter = Now<NodeSeconds>();
180 }
181 }
182 }
183
185}
186
188 if (vRecv.empty()) {
189 return false;
190 }
191
192 const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
193
194 do {
195 CDataStream::iterator pstart = std::search(
196 vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
197 uint32_t nHeaderSize =
199 if (vRecv.end() - pstart < nHeaderSize) {
200 if (vRecv.size() > nHeaderSize) {
201 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
202 }
203 break;
204 }
205 vRecv.erase(vRecv.begin(), pstart);
206 std::vector<std::byte> vHeaderSave(vRecv.begin(),
207 vRecv.begin() + nHeaderSize);
208 CMessageHeader hdr(netMagic);
209 vRecv >> hdr;
210 if (!hdr.IsValidWithoutConfig(netMagic)) {
211 // tfm::format(std::cout, "%s: BAD (invalid header)\n",
212 // ToString(you));
213 ban = 100000;
214 return true;
215 }
216 std::string strCommand = hdr.GetCommand();
217 unsigned int nMessageSize = hdr.nMessageSize;
218 if (nMessageSize > MAX_SIZE) {
219 // tfm::format(std::cout, "%s: BAD (message too large)\n",
220 // ToString(you));
221 ban = 100000;
222 return true;
223 }
224 if (nMessageSize > vRecv.size()) {
225 vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
226 break;
227 }
228 if (vRecv.GetVersion() >= 209) {
229 uint256 hash = Hash(Span{vRecv}.first(nMessageSize));
230 if (memcmp(hash.begin(), hdr.pchChecksum,
232 continue;
233 }
234 }
235 std::vector<std::byte> vec{vRecv.begin(), vRecv.begin() + nMessageSize};
237 vRecv.GetVersion());
238 vRecv.ignore(nMessageSize);
239 if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
240 return true;
241 }
242 // tfm::format(std::cout, "%s: done processing %s\n",
243 // ToString(you),
244 // strCommand);
245 } while (1);
246 return false;
247}
248
249CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
250 : vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), vAddr(vAddrIn), you(ip),
251 checkpointVerified(!HasCheckpoint()) {
252 if (GetTime() > 1329696000) {
253 vSend.SetVersion(209);
254 vRecv.SetVersion(209);
255 }
256}
257
259 // FIXME: This logic is duplicated with CConnman::ConnectNode for no
260 // good reason.
261 bool connected = false;
262 proxyType proxy;
263
264 if (you.IsValid()) {
265 bool proxyConnectionFailed = false;
266
267 if (GetProxy(you.GetNetwork(), proxy)) {
268 sock = CreateSock(proxy.proxy);
269 if (!sock) {
270 return false;
271 }
272 connected = ConnectThroughProxy(
274 proxyConnectionFailed);
275 } else {
276 // no proxy needed (none set for target network)
278 if (!sock) {
279 return false;
280 }
281 // no proxy needed (none set for target network)
282 connected =
284 }
285 }
286
287 if (!connected) {
288 // tfm::format(std::cout, "Cannot connect to %s\n",
289 // ToString(you));
290 sock.reset();
291 return false;
292 }
293
294 // Write version message
295 // Don't include the time in CAddress serialization. See D14753.
296 uint64_t nLocalServices = 0;
297 uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
298 uint64_t your_services{yourServices};
299 uint64_t my_services{ServiceFlags(NODE_NETWORK)};
300 uint8_t fRelayTxs = 0;
301
302 const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
303 const std::string clientVersion =
304 gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
305 const std::string userAgent =
306 FormatUserAgent(clientName, clientVersion, {"seeder"});
307
309 nLocalServices, GetTime(), your_services, you,
310 my_services, CService(), nLocalNonce, userAgent,
311 GetRequireHeight(), fRelayTxs);
312 Send();
313
314 bool res = true;
315 NodeSeconds now;
316 while (now = Now<NodeSeconds>(),
317 ban == 0 &&
318 (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
319 doneAfter > now) &&
320 sock) {
321 char pchBuf[0x10000];
322 fd_set fdsetRecv;
323 fd_set fdsetError;
324 FD_ZERO(&fdsetRecv);
325 FD_ZERO(&fdsetError);
326 FD_SET(sock->Get(), &fdsetRecv);
327 FD_SET(sock->Get(), &fdsetError);
328 struct timeval wa;
329 if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) != 0) {
330 wa.tv_sec = (doneAfter - now).count();
331 wa.tv_usec = 0;
332 } else {
333 wa.tv_sec = GetTimeout().count();
334 wa.tv_usec = 0;
335 }
336 int ret =
337 select(sock->Get() + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
338 if (ret != 1) {
339 if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0) {
340 res = false;
341 }
342 break;
343 }
344 int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
345 int nPos = vRecv.size();
346 if (nBytes > 0) {
347 vRecv.resize(nPos + nBytes);
348 memcpy(&vRecv[nPos], pchBuf, nBytes);
349 } else if (nBytes == 0) {
350 // tfm::format(std::cout, "%s: BAD (connection closed
351 // prematurely)\n",
352 // ToString(you));
353 res = false;
354 break;
355 } else {
356 // tfm::format(std::cout, "%s: BAD (connection error)\n",
357 // ToString(you));
358 res = false;
359 break;
360 }
362 Send();
363 }
364 if (!sock) {
365 res = false;
366 }
367 sock.reset();
368 return (ban == 0) && res;
369}
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
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:23
BlockHash hashPrevBlock
Definition: block.h:27
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:177
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:119
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:626
bool IsValid() const
Definition: netaddress.cpp:477
enum Network GetNetwork() const
Definition: netaddress.cpp:549
CDataStream vRecv
Definition: bitcoin.h:43
CService you
Definition: bitcoin.h:50
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:249
CDataStream vSend
Definition: bitcoin.h:42
bool Run()
Definition: bitcoin.cpp:258
int nStartingHeight
Definition: bitcoin.h:46
bool needAddrReply
Definition: bitcoin.h:53
int nVersion
Definition: bitcoin.h:44
std::vector< CAddress > * vAddr
Definition: bitcoin.h:47
ServiceFlags yourServices
Definition: bitcoin.h:51
bool ProcessMessages()
Definition: bitcoin.cpp:187
std::string strSubVer
Definition: bitcoin.h:45
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:41
void Send()
Definition: bitcoin.cpp:26
std::chrono::seconds GetTimeout()
Definition: bitcoin.h:55
bool checkpointVerified
Definition: bitcoin.h:52
int ban
Definition: bitcoin.h:48
NodeSeconds doneAfter
Definition: bitcoin.h:49
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:60
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: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 * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
Definition: protocol.cpp:29
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:3431
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:715
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:758
std::function< std::unique_ptr< Sock >(const CService &)> CreateSock
Socket factory.
Definition: netbase.cpp:615
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:629
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:24
PeerMessagingState
Definition: bitcoin.h:26
static const unsigned int ADDR_SOFT_CAP
Definition: bitcoin.h:24
static int GetRequireHeight()
Definition: db.h:28
static bool HasCheckpoint()
Definition: db.h:32
#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
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:413
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()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
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