Bitcoin ABC 0.32.6
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 DataStream &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 >> WithParams(CNetAddr::V1, 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
68 }
69
70 if (strCommand == NetMsgType::VERACK) {
71 // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
72 // nVersion);
73 auto doneAfterDelta{1s};
74 // Note in the current codebase: vAddr is non-nullptr only once per day
75 // for each node we check
76 if (vAddr) {
78 doneAfterDelta = GetTimeout();
79 needAddrReply = true;
80 }
81
82 // request headers starting after last checkpoint (only if we have
83 // checkpoints for this network)
84 if (HasCheckpoint()) {
85 std::vector<BlockHash> locatorHash(
86 1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
88 CBlockLocator(std::move(locatorHash)),
89 uint256());
90 }
91 doneAfter = Now<NodeSeconds>() + doneAfterDelta;
93 }
94
95 if (strCommand == NetMsgType::ADDR && vAddr) {
96 needAddrReply = false;
97 std::vector<CAddress> vAddrNew;
98 recv >> WithParams(CAddress::V1_NETWORK, vAddrNew);
99 // tfm::format(std::cout, "%s: got %i addresses\n",
100 // ToString(you),
101 // (int)vAddrNew.size());
102 auto now = Now<NodeSeconds>();
103 std::vector<CAddress>::iterator it = vAddrNew.begin();
104 if (vAddrNew.size() > 1) {
105 if (checkpointVerified &&
106 (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
107 doneAfter > now + 1s)) {
108 doneAfter = now + 1s;
109 }
110 }
111 while (it != vAddrNew.end()) {
112 CAddress &addr = *it;
113 // tfm::format(std::cout, "%s: got address %s\n",
114 // ToString(you),
115 // addr.ToString(), (int)(vAddr->size()));
116 it++;
117 if (addr.nTime <= NodeSeconds{100000000s} ||
118 addr.nTime > now + 10min) {
119 addr.nTime = now - 5 * 24h;
120 }
121 if (addr.nTime > now - 7 * 24h) {
122 vAddr->push_back(addr);
123 }
124 // tfm::format(std::cout, "%s: added address %s (#%i)\n",
125 // ToString(you),
126 // addr.ToString(), (int)(vAddr->size()));
127 if (vAddr->size() > ADDR_SOFT_CAP) {
128 if (!checkpointVerified) {
129 // stop processing addresses now since we hit the soft cap,
130 // but we will continue to await headers
131 break;
132 }
133 // stop processing addresses and since we aren't waiting for
134 // headers, stop processing immediately
135 doneAfter = now;
137 }
138 }
140 }
141
142 if (strCommand == NetMsgType::HEADERS) {
143 uint64_t nCount = ReadCompactSize(recv);
144 if (nCount == 0) {
145 // Empty HEADERS messages can be sent when the peer does not have
146 // enough chainwork.
148 }
149 if (nCount > MAX_HEADERS_RESULTS) {
150 ban = 100000;
152 }
153
154 CBlockHeader header;
155 recv >> header;
156
157 // If the peer has a chain longer than our last checkpoint, we expect
158 // that the first header it will send will be the one just after
159 // that checkpoint, as we claim to have the checkpoint as our starting
160 // height in the version message.
162 if (header.hashPrevBlock !=
163 Params().Checkpoints().mapCheckpoints.rbegin()->second) {
164 // This node is synced higher than the last checkpoint height
165 // but does not have the checkpoint block in its chain.
166 // This means it must be on the wrong chain. We treat these
167 // nodes the same as nodes with the wrong net magic.
168 // std::fprintf(stdout, "%s: BAD \"%s\" (wrong chain)\n",
169 // ToString(you).c_str(), strSubVer.c_str());
170 ban = 100000;
172 }
173 checkpointVerified = true;
174 if (!needAddrReply) {
175 // we are no longer waiting for headers or addr, so we can
176 // stop processing this node
177 doneAfter = Now<NodeSeconds>();
178 }
179 }
180 }
181
183}
184
186 if (vRecv.empty()) {
187 return false;
188 }
189
190 const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
191
192 do {
193 DataStream::iterator pstart = std::search(
194 vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
195 uint32_t nHeaderSize = GetSerializeSize(CMessageHeader(netMagic));
196 if (vRecv.end() - pstart < nHeaderSize) {
197 if (vRecv.size() > nHeaderSize) {
198 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
199 }
200 break;
201 }
202 vRecv.erase(vRecv.begin(), pstart);
203 std::vector<std::byte> vHeaderSave(vRecv.begin(),
204 vRecv.begin() + nHeaderSize);
205 CMessageHeader hdr(netMagic);
206 vRecv >> hdr;
207 if (!hdr.IsValidWithoutConfig(netMagic)) {
208 // tfm::format(std::cout, "%s: BAD (invalid header)\n",
209 // ToString(you));
210 ban = 100000;
211 return true;
212 }
213 std::string strCommand = hdr.GetMessageType();
214 unsigned int nMessageSize = hdr.nMessageSize;
215 if (nMessageSize > MAX_SIZE) {
216 // tfm::format(std::cout, "%s: BAD (message too large)\n",
217 // ToString(you));
218 ban = 100000;
219 return true;
220 }
221 if (nMessageSize > vRecv.size()) {
222 vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
223 break;
224 }
225 uint256 hash = Hash(Span{vRecv}.first(nMessageSize));
226 if (memcmp(hash.begin(), hdr.pchChecksum,
228 continue;
229 }
230 std::vector<std::byte> vec{vRecv.begin(), vRecv.begin() + nMessageSize};
231 DataStream vMsg{MakeUCharSpan(vec)};
232 vRecv.ignore(nMessageSize);
233 if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
234 return true;
235 }
236 // tfm::format(std::cout, "%s: done processing %s\n",
237 // ToString(you),
238 // strCommand);
239 } while (1);
240 return false;
241}
242
243CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
244 : vAddr(vAddrIn), you(ip), checkpointVerified(!HasCheckpoint()) {}
245
247 // FIXME: This logic is duplicated with CConnman::ConnectNode for no
248 // good reason.
249 bool connected = false;
250 proxyType proxy;
251
252 if (you.IsValid()) {
253 bool proxyConnectionFailed = false;
254
255 if (GetProxy(you.GetNetwork(), proxy)) {
256 sock = CreateSock(proxy.proxy);
257 if (!sock) {
258 return false;
259 }
260 connected = ConnectThroughProxy(
262 proxyConnectionFailed);
263 } else {
264 // no proxy needed (none set for target network)
266 if (!sock) {
267 return false;
268 }
269 // no proxy needed (none set for target network)
270 connected =
272 }
273 }
274
275 if (!connected) {
276 // tfm::format(std::cout, "Cannot connect to %s\n",
277 // ToString(you));
278 sock.reset();
279 return false;
280 }
281
282 // Write version message
283 // Don't include the time in CAddress serialization. See D14753.
284 uint64_t nLocalServices = 0;
285 uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
286 uint64_t your_services{yourServices};
287 uint64_t my_services{ServiceFlags(NODE_NETWORK)};
288 uint8_t fRelayTxs = 0;
289
290 const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
291 const std::string clientVersion =
292 gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
293 const std::string userAgent =
294 FormatUserAgent(clientName, clientVersion, {"seeder"});
295
298 your_services, WithParams(CNetAddr::V1, you), my_services,
299 WithParams(CNetAddr::V1, CService{}), nLocalNonce, userAgent,
300 GetRequireHeight(), fRelayTxs);
301 Send();
302
303 bool res = true;
304 NodeSeconds now;
305 while (now = Now<NodeSeconds>(),
306 ban == 0 &&
307 (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
308 doneAfter > now) &&
309 sock) {
310 char pchBuf[0x10000];
311 fd_set fdsetRecv;
312 fd_set fdsetError;
313 FD_ZERO(&fdsetRecv);
314 FD_ZERO(&fdsetError);
315 FD_SET(sock->Get(), &fdsetRecv);
316 FD_SET(sock->Get(), &fdsetError);
317 struct timeval wa;
318 if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) != 0) {
319 wa.tv_sec = (doneAfter - now).count();
320 wa.tv_usec = 0;
321 } else {
322 wa.tv_sec = GetTimeout().count();
323 wa.tv_usec = 0;
324 }
325 int ret =
326 select(sock->Get() + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
327 if (ret != 1) {
328 if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0) {
329 res = false;
330 }
331 break;
332 }
333 int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
334 int nPos = vRecv.size();
335 if (nBytes > 0) {
336 vRecv.resize(nPos + nBytes);
337 memcpy(&vRecv[nPos], pchBuf, nBytes);
338 } else if (nBytes == 0) {
339 // tfm::format(std::cout, "%s: BAD (connection closed
340 // prematurely)\n",
341 // ToString(you));
342 res = false;
343 break;
344 } else {
345 // tfm::format(std::cout, "%s: BAD (connection error)\n",
346 // ToString(you));
347 res = false;
348 break;
349 }
351 Send();
352 }
353 if (!sock) {
354 res = false;
355 }
356 sock.reset();
357 return (ban == 0) && res;
358}
ArgsManager gArgs
Definition: args.cpp:40
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:21
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:463
A CService with information about it as peer.
Definition: protocol.h:443
static constexpr SerParams V1_NETWORK
Definition: protocol.h:496
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
Definition: protocol.h:553
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:100
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:180
static constexpr size_t CHECKSUM_SIZE
Definition: protocol.h:39
std::string GetMessageType() const
Definition: protocol.cpp:120
uint8_t pchChecksum[CHECKSUM_SIZE]
Definition: protocol.h:73
uint32_t nMessageSize
Definition: protocol.h:72
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:47
std::string ToStringIP() const
Definition: netaddress.cpp:623
static constexpr SerParams V1
Definition: netaddress.h:255
bool IsValid() const
Definition: netaddress.cpp:474
enum Network GetNetwork() const
Definition: netaddress.cpp:546
CService you
Definition: bitcoin.h:50
DataStream vSend
Definition: bitcoin.h:42
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:243
bool Run()
Definition: bitcoin.cpp:246
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:185
std::string strSubVer
Definition: bitcoin.h:45
void Send()
Definition: bitcoin.cpp:26
std::chrono::seconds GetTimeout()
Definition: bitcoin.h:55
DataStream vRecv
Definition: bitcoin.h:43
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
PeerMessagingState ProcessMessage(std::string strCommand, DataStream &recv)
Definition: bitcoin.cpp:41
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:573
uint16_t GetPort() const
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:118
bool empty() const
Definition: streams.h:152
size_type size() const
Definition: streams.h:151
void resize(size_type n, value_type c=value_type{})
Definition: streams.h:153
void insert(iterator it, std::vector< value_type >::const_iterator first, std::vector< value_type >::const_iterator last)
Definition: streams.h:168
iterator erase(iterator it)
Definition: streams.h:203
const_iterator begin() const
Definition: streams.h:147
vector_type::iterator iterator
Definition: streams.h:131
void ignore(size_t num_ignore)
Definition: streams.h:276
const_iterator end() const
Definition: streams.h:149
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:94
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:74
Block-chain checkpoints are compiled-in sanity checks.
Definition: checkpoints.cpp:9
static void WriteMessage(DataStream &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:3140
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:730
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:773
std::function< std::unique_ptr< Sock >(const CService &)> CreateSock
Socket factory.
Definition: netbase.cpp:630
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:644
int nConnectTimeout
Definition: netbase.cpp:37
ServiceFlags
nServices flags.
Definition: protocol.h:336
@ NODE_NETWORK
Definition: protocol.h:343
static const int PROTOCOL_VERSION
network protocol versioning
#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:27
static bool HasCheckpoint()
Definition: db.h:31
#define BEGIN(a)
Definition: util.h:10
#define END(a)
Definition: util.h:11
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1262
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:34
static auto WithParams(const Params &params, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params.
Definition: serialize.h:1329
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:469
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:350
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:108
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:105
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition: time.h:25