Bitcoin ABC 0.34.2
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 try {
44 // tfm::format(std::cout, "%s: RECV %s\n", ToString(you),
45 // strCommand);
46 if (strCommand == NetMsgType::VERSION) {
47 int64_t nTime;
48 CService addrMe;
49 uint64_t nNonce = 1;
50 uint64_t nServiceInt;
51 recv >> nVersion >> nServiceInt >> nTime;
52 yourServices = ServiceFlags(nServiceInt);
53 // Ignore the addrMe service bits sent by the peer
54 recv.ignore(8);
55 recv >> WithParams(CNetAddr::V1, addrMe);
56
57 // The version message includes information about the sending node
58 // which we don't use:
59 // - 8 bytes (service bits)
60 // - 16 bytes (ipv6 address)
61 // - 2 bytes (port)
62 recv.ignore(26);
63 recv >> nNonce;
65 recv >> nStartingHeight;
66
69 }
70
71 if (strCommand == NetMsgType::VERACK) {
72 // tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
73 // nVersion);
74 auto doneAfterDelta{1s};
75 // Note in the current codebase: vAddr is non-nullptr only once per
76 // day for each node we check
77 if (vAddr) {
79 doneAfterDelta = GetTimeout();
80 needAddrReply = true;
81 }
82
83 // request headers starting after last checkpoint (only if we have
84 // checkpoints for this network)
85 if (HasCheckpoint()) {
86 std::vector<BlockHash> locatorHash(
87 1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
90 CBlockLocator(std::move(locatorHash)), uint256());
91 }
92 doneAfter = Now<NodeSeconds>() + doneAfterDelta;
94 }
95
96 if (strCommand == NetMsgType::ADDR && vAddr) {
97 needAddrReply = false;
98 std::vector<CAddress> vAddrNew;
99 recv >> WithParams(CAddress::V1_NETWORK, vAddrNew);
100 // tfm::format(std::cout, "%s: got %i addresses\n",
101 // ToString(you),
102 // (int)vAddrNew.size());
103 auto now = Now<NodeSeconds>();
104 std::vector<CAddress>::iterator it = vAddrNew.begin();
105 if (vAddrNew.size() > 1) {
106 if (checkpointVerified &&
107 (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
108 doneAfter > now + 1s)) {
109 doneAfter = now + 1s;
110 }
111 }
112 while (it != vAddrNew.end()) {
113 CAddress &addr = *it;
114 // tfm::format(std::cout, "%s: got address %s\n",
115 // ToString(you),
116 // addr.ToString(), (int)(vAddr->size()));
117 it++;
118 if (addr.nTime <= NodeSeconds{100000000s} ||
119 addr.nTime > now + 10min) {
120 addr.nTime = now - 5 * 24h;
121 }
122 if (addr.nTime > now - 7 * 24h) {
123 vAddr->push_back(addr);
124 }
125 // tfm::format(std::cout, "%s: added address %s (#%i)\n",
126 // ToString(you),
127 // addr.ToString(), (int)(vAddr->size()));
128 if (vAddr->size() > ADDR_SOFT_CAP) {
129 if (!checkpointVerified) {
130 // stop processing addresses now since we hit the soft
131 // cap, but we will continue to await headers
132 break;
133 }
134 // stop processing addresses and since we aren't waiting for
135 // headers, stop processing immediately
136 doneAfter = now;
138 }
139 }
141 }
142
143 if (strCommand == NetMsgType::HEADERS) {
144 uint64_t nCount = ReadCompactSize(recv);
145 if (nCount == 0) {
146 // Empty HEADERS messages can be sent when the peer does not
147 // have enough chainwork.
149 }
150 if (nCount > MAX_HEADERS_RESULTS) {
151 ban = 100000;
153 }
154
155 CBlockHeader header;
156 recv >> header;
157
158 // If the peer has a chain longer than our last checkpoint, we
159 // expect that the first header it will send will be the one just
160 // after that checkpoint, as we claim to have the checkpoint as our
161 // starting height in the version message.
163 if (header.hashPrevBlock !=
164 Params().Checkpoints().mapCheckpoints.rbegin()->second) {
165 // This node is synced higher than the last checkpoint
166 // height but does not have the checkpoint block in its
167 // chain. This means it must be on the wrong chain. We treat
168 // these nodes the same as nodes with the wrong net magic.
169 // std::fprintf(stdout, "%s: BAD \"%s\" (wrong chain)\n",
170 // ToString(you).c_str(), strSubVer.c_str());
171 ban = 100000;
173 }
174 checkpointVerified = true;
175 if (!needAddrReply) {
176 // we are no longer waiting for headers or addr, so we can
177 // stop processing this node
178 doneAfter = Now<NodeSeconds>();
179 }
180 }
181 }
182
184 } catch (const std::ios_base::failure &) {
185 // Treat malformed/oversized payloads as a rejected peer message so the
186 // probe finishes normally (ban + socket cleanup) instead of unwinding.
187 ban = 100000;
189 }
190}
191
193 if (vRecv.empty()) {
194 return false;
195 }
196
197 const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
198
199 do {
200 DataStream::iterator pstart = std::search(
201 vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
202 uint32_t nHeaderSize = GetSerializeSize(CMessageHeader());
203 if (vRecv.end() - pstart < nHeaderSize) {
204 if (vRecv.size() > nHeaderSize) {
205 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
206 }
207 break;
208 }
209 vRecv.erase(vRecv.begin(), pstart);
210 std::vector<std::byte> vHeaderSave(vRecv.begin(),
211 vRecv.begin() + nHeaderSize);
212 CMessageHeader hdr;
213 vRecv >> hdr;
214 if (!hdr.IsMessageTypeValid()) {
215 // tfm::format(std::cout, "%s: BAD (invalid header)\n",
216 // ToString(you));
217 ban = 100000;
218 return true;
219 }
220 std::string strCommand = hdr.GetMessageType();
221 unsigned int nMessageSize = hdr.nMessageSize;
222 if (nMessageSize > MAX_SIZE) {
223 // tfm::format(std::cout, "%s: BAD (message too large)\n",
224 // ToString(you));
225 ban = 100000;
226 return true;
227 }
228 if (nMessageSize > vRecv.size()) {
229 vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
230 break;
231 }
232 uint256 hash = Hash(Span{vRecv}.first(nMessageSize));
233 if (memcmp(hash.begin(), hdr.pchChecksum,
235 continue;
236 }
237 std::vector<std::byte> vec{vRecv.begin(), vRecv.begin() + nMessageSize};
238 DataStream vMsg{MakeUCharSpan(vec)};
239 vRecv.ignore(nMessageSize);
240 if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
241 return true;
242 }
243 // tfm::format(std::cout, "%s: done processing %s\n",
244 // ToString(you),
245 // strCommand);
246 } while (1);
247 return false;
248}
249
250CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
251 : vAddr(vAddrIn), you(ip), checkpointVerified(!HasCheckpoint()) {}
252
254 // FIXME: This logic is duplicated with CConnman::ConnectNode for no
255 // good reason.
256 Proxy proxy;
257
258 if (you.IsValid()) {
259 bool proxyConnectionFailed = false;
260
261 if (GetProxy(you.GetNetwork(), proxy)) {
263 proxyConnectionFailed);
264 } else {
265 // no proxy needed (none set for target network)
266 sock = ConnectDirectly(you, false);
267 }
268 }
269
270 if (!sock) {
271 // tfm::format(std::cout, "Cannot connect to %s\n",
272 // ToString(you));
273 return false;
274 }
275
276 // Write version message
277 // Don't include the time in CAddress serialization. See D14753.
278 uint64_t nLocalServices = 0;
279 uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
280 uint64_t your_services{yourServices};
281 uint64_t my_services{ServiceFlags(NODE_NETWORK)};
282 uint8_t fRelayTxs = 0;
283
284 const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
285 const std::string clientVersion =
286 gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
287 const std::string userAgent =
288 FormatUserAgent(clientName, clientVersion, {"seeder"});
289
292 your_services, WithParams(CNetAddr::V1, you), my_services,
293 WithParams(CNetAddr::V1, CService{}), nLocalNonce, userAgent,
294 GetRequireHeight(), fRelayTxs);
295 Send();
296
297 bool res = true;
298 NodeSeconds now;
299 while (now = Now<NodeSeconds>(),
300 ban == 0 &&
301 (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
302 doneAfter > now) &&
303 sock) {
304 char pchBuf[0x10000];
305 struct timeval wa;
306 if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) != 0) {
307 wa.tv_sec = (doneAfter - now).count();
308 wa.tv_usec = 0;
309 } else {
310 wa.tv_sec = GetTimeout().count();
311 wa.tv_usec = 0;
312 }
313 if (sock->WaitReadableOrException(&wa) != 1) {
314 if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0) {
315 res = false;
316 }
317 break;
318 }
319 int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
320 int nPos = vRecv.size();
321 if (nBytes > 0) {
322 vRecv.resize(nPos + nBytes);
323 memcpy(&vRecv[nPos], pchBuf, nBytes);
324 } else if (nBytes == 0) {
325 // tfm::format(std::cout, "%s: BAD (connection closed
326 // prematurely)\n",
327 // ToString(you));
328 res = false;
329 break;
330 } else {
331 // tfm::format(std::cout, "%s: BAD (connection error)\n",
332 // ToString(you));
333 res = false;
334 break;
335 }
337 Send();
338 }
339 if (!sock) {
340 res = false;
341 }
342 sock.reset();
343 return (ban == 0) && res;
344}
ArgsManager gArgs
Definition: args.cpp:39
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:462
A CService with information about it as peer.
Definition: protocol.h:442
static constexpr SerParams V1_NETWORK
Definition: protocol.h:495
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
Definition: protocol.h:552
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 IsMessageTypeValid() const
Definition: protocol.cpp:125
static constexpr size_t CHECKSUM_SIZE
Definition: protocol.h:39
std::string GetMessageType() const
Definition: protocol.cpp:119
uint8_t pchChecksum[CHECKSUM_SIZE]
Definition: protocol.h:72
uint32_t nMessageSize
Definition: protocol.h:71
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:47
std::string ToStringAddr() const
Definition: netaddress.cpp:630
static constexpr SerParams V1
Definition: netaddress.h:255
bool IsValid() const
Definition: netaddress.cpp:477
enum Network GetNetwork() const
Definition: netaddress.cpp:553
CService you
Definition: bitcoin.h:50
DataStream vSend
Definition: bitcoin.h:42
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:250
bool Run()
Definition: bitcoin.cpp:253
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:192
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:277
const_iterator end() const
Definition: streams.h:149
Definition: netbase.h:67
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:94
constexpr uint8_t * begin()
Definition: uint256.h:122
256-bit opaque blob.
Definition: uint256.h:199
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:3256
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
Definition: net.h:71
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
std::unique_ptr< Sock > ConnectDirectly(const CService &dest, bool manual_connection)
Create a socket and try to connect to the specified service.
Definition: netbase.cpp:732
bool GetProxy(enum Network net, Proxy &proxyInfoOut)
Definition: netbase.cpp:809
std::unique_ptr< Sock > ConnectThroughProxy(const Proxy &proxy, const std::string &dest, uint16_t port, bool &proxy_connection_failed)
Connect to a specified destination service through a SOCKS5 proxy by first connecting to the SOCKS5 p...
Definition: netbase.cpp:852
ServiceFlags
nServices flags.
Definition: protocol.h:335
@ NODE_NETWORK
Definition: protocol.h:342
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:1264
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
#define LIMITED_STRING(obj, n)
Definition: serialize.h:637
static auto WithParams(const Params &params, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params.
Definition: serialize.h:1331
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
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:80
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition: time.h:27