// Copyright (c) 2009 Satoshi Nakamoto // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. class CMessageHeader; class CAddress; class CInv; class CNode; // Defined in main.h, which is included after this file. Only ever used here as // a pointer, so the forward declaration is enough. class CBlockIndex; // Held in host byte order, unlike the DEFAULT_PORT constant these replace, // which was htons(8433). Nothing is lost: net.cpp's GetDefaultPort() applies // htons() itself and is what every caller now uses, so the value that reaches // a sockaddr is byte-for-byte what it was. Mainnet stays on 8433. static const unsigned short MAINNET_PORT = 8433; static const unsigned short TESTNET_PORT = 18433; static const unsigned int PUBLISH_HOPS = 5; enum { NODE_NETWORK = (1 << 0), }; // Defined in main.cpp. True while this node is tracking the tip rather than // still catching up, measured off the age of our own best block -- see there // for why that and not a peer-reported height. Declared here because net.h is // parsed before main.h and CNode::AskFor needs it. bool IsBlockFetchNearTip(); bool GetMyExternalIP(unsigned int& ipRet); bool IsTestNet(); unsigned short GetDefaultPort(); void SelectNetworkParams(bool fTestNetIn); CNode* ConnectNodeBtf(const string& strBtfAddr); CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, const string& strOnion, const unsigned char enc_pub[32], const string& strDesc=string()); void ThreadBtfAccept(void* parg); void ThreadBtfConnect(void* parg); extern string strBtfConnect; extern bool fBtfOnionOnly; // Bootstrap seeds added at runtime with /btfseed=ADDRESS:ENCHEX (repeatable). // The compiled-in list lives in net.cpp; these are appended to it. extern std::vector > vBtfExtraSeeds; // --- .btf peer exchange --------------------------------------------------- // Peers gossip signed descriptors so discovery survives a relay outage. Both // caps apply to a single "btfpeers" message; the generic header limit is 256 MB, // which is no protection at all for something a stranger can send unprompted. static const unsigned int MAX_PEX_DESCRIPTORS = 20; static const unsigned int MAX_PEX_DESCRIPTOR_BYTES = 1024; // Ignore a peer's exchange more often than this. One announcement per side per // connection is the intended traffic; anything faster is someone else's idea. static const int64 PEX_MIN_INTERVAL = 60; // How long to sit registered at a rendezvous relay before giving up on this // attempt and registering again. Bounded because a registration socket that // goes quiet is indistinguishable, from inside recv(), from one whose path has // died -- and the second kind never wakes up. Five minutes is short enough // that a node is unreachable only briefly and long enough that the reconnect // traffic is nothing: one per relay per five minutes. static const int BTF_RENDEZVOUS_WAIT_SECS = 300; // Registrations this node parks at a rendezvous at once. // // Back to one, and it stays at one until every relay in vBtfMeetingRelays runs // the queue from #113. More than one is what keeps a node reachable while one // registration is being paired -- but only against a relay that accepts more // than one. An older relay closes the previous registration whenever the same // node registers again, so several accept threads pointed at one of those // evict each other in a loop: thread 2 registers and kills thread 1, thread 3 // kills thread 2, thread 1 sees its socket die and kills thread 3. // // #113 called that harmless. It is not. Measured on a node running three // threads against the un-upgraded New Jersey relay: 189 registrations in about // fifteen minutes -- roughly twelve a minute -- and not one pairing. The node // was not merely failing to benefit, it was unreachable through that relay and // hammering it. A node with one thread does none of this. // // The bench that approved #113 could not see it: its harness re-registers by // design, which is exactly what hides an eviction loop. // // Raise this to 3 only when the other two relays are upgraded. static const int BTF_ACCEPT_THREADS = 1; // Liveness of an established peer connection. BTF_RENDEZVOUS_WAIT_SECS bounds // the wait for a dial to arrive; these bound the connection that comes out of // it, which has the same failure mode once it goes quiet. // // A healthy peer relays a block inventory roughly every nTargetSpacing (two // minutes), so silence measured in block intervals is the honest signal. // Bitcoin used ninety minutes against ten-minute blocks -- nine intervals -- // and the same nine intervals here is eighteen minutes; thirty leaves margin // for a slow stretch without letting a dead path last an hour. static const int BTF_RECV_TIMEOUT_SECS = 30 * 60; static const int BTF_SEND_STALL_SECS = 10 * 60; static const int BTF_HANDSHAKE_GRACE_SECS = 60; // How long a requested block gets before it is asked for again, in seconds. // Used twice: CNode::AskFor spaces the queued per-announcer block retries this // far apart instead of the two minutes transactions get, and the failover // sweep in main.cpp re-issues a getdata to a different peer once a sent // request has gone unanswered this long. A block body is at most 1 MB and // somebody demonstrably has it -- they announced it -- so on this timescale // "not here yet" means "not coming from that peer", not "still in transit". static const int BLOCK_FETCH_RETRY_SECS = 15; // A serialized object cannot be larger than MAX_SIZE, so no valid network // message needs the old 256 MB header allowance. Keep the wire cap aligned with // what the deserializer can accept. How long a peer may sit on a partial // payload after a complete header has arrived is BTF_MSG_WAIT_MAX_SECS, below. static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; // Ceiling on simultaneous connections. // // ThreadSocketHandler watches every peer in one socket loop. This used to be a // select() loop, which made FD_SETSIZE the real limit and silently starved // sockets past that bitmap. It is now poll()/WSAPoll(), so the ceiling below is // a deliberate resource bound rather than a descriptor-set accident. // // Measured on two nodes before this ceiling existed: 277 and 90 CNode objects // against 93 and 90 live sockets, and a status bar reporting hundreds of // peers for a node that was really talking to thirty. // // 125 is Bitcoin's number and remains a conservative public-node default. static const unsigned int MAX_CONNECTIONS = 125; // Cap inbound connections from any single address. Without it one source can // hold every slot up to MAX_CONNECTIONS -- exactly what happened to the // rendezvous relays, where a single IP parked hundreds of connections and // starved real peers. A legitimate peer, even a relay talking to a relay, // needs only a handful; 32 leaves generous room while denying any one address // more than a quarter of the table. The firewall connlimit on the relays does // the same thing a layer lower; this makes every build carry the defense. // // Loopback (127.0.0.0/8) is exempt in the accept path. A managed-Tor node // receives every inbound onion peer over its local hidden-service listener, so // they all appear as 127.0.0.1 -- capping loopback would cap onion peers as a // group, which is exactly wrong for a network moving toward onion-only. The // global MAX_CONNECTIONS still bounds the total; a per-onion-identity limit, // applied once identity is known after accept(), is the right future tool for // onion floods. static const unsigned int MAX_CONNECTIONS_PER_IP = 32; // A node marked for disconnect is normally held until its buffers drain, so // a last message still goes out. But vSend cannot drain through a socket // whose far end is gone, and that made such a node immortal: it stayed in // vNodes, kept its socket open, and kept being counted. Force it out after // this long regardless of what is still buffered. static const int64 DISCONNECT_DRAIN_SECS = 60; // How long a pool may go without hearing a height from ANY peer before it // stops issuing jobs. Long enough that ordinary peer churn and a quiet // handshake window do not trip it; short enough that a deaf pool cannot build // more than a few blocks of private fork before it is stopped. Heights // 3966-4085 -- 120 blocks, 5890.50 BTF -- were mined in exactly this state. static const int64 BTF_NO_PEER_HEIGHT_MAX_SECS = 20 * 60; // How long a peer may leave this node waiting for the rest of a message it // announced in a header. // // ProcessMessages rewinds the header and breaks when the body has not all // arrived, which is correct for a message still in flight and unbounded for // one that never completes: the same header is re-read, the loop breaks // again, and that peer is never parsed again for the life of the process. // Satoshi left the note -- "need a mechanism to give up waiting for overlong // message size error" -- and this is it. // // It never self-corrects, because any byte that arrives refreshes nLastRecv, // so the inactivity timeout that would otherwise drop the peer never fires. // The socket stays healthy, select() keeps reporting it, and the node goes // silently deaf one peer at a time. // // A header may legitimately outrun its body by a round trip or two; two // minutes is far beyond that, and well inside BTF_RECV_TIMEOUT_SECS. static const int64 BTF_MSG_WAIT_MAX_SECS = 2 * 60; // Largest payload a peer may announce in a message header: MAX_PROTOCOL_MESSAGE_SIZE // is defined further up this file. This tree reached the same cap by the same // reasoning as upstream #109 -- a 256 MB allowance is eight times what the // deserializer will accept (serialize.h throws above MAX_SIZE), so the header // check admitted an allocation the parser would only reject later, after // BTF_MSG_WAIT_MAX_SECS of a stalled peer slot -- so only the note survives. // // Both definitions were textually clean and 59 lines apart, so the replay onto // upstream merged them without a conflict and only the compiler objected. // Send a ping after this long with nothing to say, so a peer running the // inactivity check above does not mistake a quiet node for a dead one. Must // stay well under BTF_RECV_TIMEOUT_SECS. static const int BTF_PING_INTERVAL_SECS = 10 * 60; // How long a node must stay behind the network before it says so, and how // often it repeats itself. Five minutes is two and a half block intervals -- // long enough that ordinary relay lag never trips it. static const int BTF_BEHIND_GRACE_SECS = 5 * 60; static const int BTF_BEHIND_WARN_INTERVAL_SECS = 5 * 60; // --- Self-diagnosis ------------------------------------------------------- // // A node that has stopped working looks exactly like a node with nothing to // do. That has cost this project real time more than once: a node deaf to // most of its peers, a miner allocating one RandomX dataset per thread, a // third of arriving blocks missing their parent -- each was found from // outside, by reading the process's sockets or its memory from another // machine, because the node itself had no way to say so. // // These counters exist so it can. Cheap to keep, and they name the failures // that actually happened rather than the ones that sound impressive. extern int nPeersWatched; // peers in the last poll() set extern int64 nBlocksReceived; // blocks handed to ProcessBlock extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned // One report, rendered the same way for the GUI panel and the log, so what a // user pastes into an issue is what a developer already knows how to read. string GetDiagnosticsText(); #include "sockcount.h" // Defined in main.cpp. Declared here because CNode announces it in the version // message, and net.h is included before main.h. extern int nBestHeight; // Median height announced by the peers we are connected to, or -1 while nobody // has told us anything. Median rather than maximum so one peer claiming an // absurd height cannot move it. int GetPeerMedianHeight(); int64 GetPeerHeightAgeSecs(); // Lightweight .btf churn accounting. These counters are diagnostics only: they // let an operator tell stale descriptors, relay pairing failures, and paired // tunnels that never speak apart before changing behaviour. void BtfChurnNoteResolveAttempt(); void BtfChurnNoteResolveResult(bool fOk); void BtfChurnNoteDialAttempt(const string& strBtfAddr, const string& strMeeting); void BtfChurnNoteDialResult(const string& strBtfAddr, const string& strMeeting, bool fOk); void BtfChurnNoteRegisterResult(const string& strMeeting, bool fOk); void BtfChurnNotePairResult(const string& strMeeting, bool fOk); void BtfChurnNoteHandshakeTimeout(const string& strBtfAddr, const string& strMeeting, bool fRecv, bool fSend); // Descriptors to hand a peer: ours first, then peers that answered us. void BtfPexCollect(std::vector& vDescOut); // Verify descriptors a peer sent and remember the good ones. Returns how many. int BtfPexAccept(const std::vector& vDesc); void ThreadBitcoinMiner(void* parg); // Starts MinerThreadCount() miners; returns how many came up. int StartMinerThreads(); bool StartNode(string& strError=REF(string())); bool StopNode(); void CheckForShutdown(int n); // // Message header // (4) message start // (12) command // (4) size // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ascii, not valid as UTF-8, and produce // a large 4-byte int at any alignment. // Magic bytes unique to the selected Bitflash network. Mainnet uses 0xbf = // "BF"; testnet swaps the whole sequence so a test node cannot handshake with // mainnet before consensus-level testnet activation exists. extern char pchMessageStart[4]; class CMessageHeader { public: enum { COMMAND_SIZE=12 }; enum { MESSAGE_START_SIZE=4 }; char pchMessageStart[MESSAGE_START_SIZE]; char pchCommand[COMMAND_SIZE]; unsigned int nMessageSize; CMessageHeader() { memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); memset(pchCommand, 0, sizeof(pchCommand)); pchCommand[1] = 1; nMessageSize = -1; } CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) { memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); strncpy(pchCommand, pszCommand, COMMAND_SIZE); nMessageSize = nMessageSizeIn; } IMPLEMENT_SERIALIZE ( READWRITE(FLATDATA(pchMessageStart)); READWRITE(FLATDATA(pchCommand)); READWRITE(nMessageSize); ) string GetCommand() { if (pchCommand[COMMAND_SIZE-1] == 0) return string(pchCommand, pchCommand + strlen(pchCommand)); else return string(pchCommand, pchCommand + COMMAND_SIZE); } bool IsValid() { // Check start string if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0) return false; // Check the command string for errors for (char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++) { if (*p1 == 0) { // Must be all zeros after the first zero for (; p1 < pchCommand + COMMAND_SIZE; p1++) if (*p1 != 0) return false; } else if (*p1 < ' ' || *p1 > 0x7E) return false; } // Message size if (nMessageSize > MAX_PROTOCOL_MESSAGE_SIZE) { if (LogAcceptsCategory("net")) printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize); return false; } return true; } }; static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; class CAddress { public: uint64 nServices; unsigned char pchReserved[12]; unsigned int ip; unsigned short port; // disk only unsigned int nTime; // memory only unsigned int nLastFailed; CAddress() { nServices = 0; memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); ip = 0; port = GetDefaultPort(); nTime = GetAdjustedTime(); nLastFailed = 0; } CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn=0) { nServices = nServicesIn; memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); ip = ipIn; port = portIn; nTime = GetAdjustedTime(); nLastFailed = 0; } explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=0) { nServices = nServicesIn; memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); ip = sockaddr.sin_addr.s_addr; port = sockaddr.sin_port; nTime = GetAdjustedTime(); nLastFailed = 0; } explicit CAddress(const char* pszIn, uint64 nServicesIn=0) { nServices = nServicesIn; memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); ip = 0; port = GetDefaultPort(); nTime = GetAdjustedTime(); nLastFailed = 0; char psz[100]; if (strlen(pszIn) > ARRAYLEN(psz)-1) return; strcpy(psz, pszIn); unsigned int a, b, c, d, e; if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4) return; char* pszPort = strchr(psz, ':'); if (pszPort) { *pszPort++ = '\0'; port = htons(atoi(pszPort)); } ip = inet_addr(psz); } IMPLEMENT_SERIALIZE ( if (nType & SER_DISK) { READWRITE(nVersion); READWRITE(nTime); } READWRITE(nServices); READWRITE(FLATDATA(pchReserved)); READWRITE(ip); READWRITE(port); ) friend inline bool operator==(const CAddress& a, const CAddress& b) { return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 && a.ip == b.ip && a.port == b.port); } friend inline bool operator<(const CAddress& a, const CAddress& b) { int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)); if (ret < 0) return true; else if (ret == 0) { if (ntohl(a.ip) < ntohl(b.ip)) return true; else if (a.ip == b.ip) return ntohs(a.port) < ntohs(b.port); } return false; } vector GetKey() const { CDataStream ss; ss.reserve(18); ss << FLATDATA(pchReserved) << ip << port; #if defined(_MSC_VER) && _MSC_VER < 1300 return vector((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]); #else return vector(ss.begin(), ss.end()); #endif } struct sockaddr_in GetSockAddr() const { struct sockaddr_in sockaddr; sockaddr.sin_family = AF_INET; sockaddr.sin_addr.s_addr = ip; sockaddr.sin_port = port; return sockaddr; } bool IsIPv4() const { return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0); } bool IsRoutable() const { return !(GetByte(3) == 10 || (GetByte(3) == 192 && GetByte(2) == 168)); } unsigned char GetByte(int n) const { return ((unsigned char*)&ip)[3-n]; } string ToStringIPPort() const { return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port)); } string ToStringIP() const { return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); } string ToString() const { return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port)); //return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); } void print() const { if (LogAcceptsCategory("net")) printf("CAddress(%s)\n", ToString().c_str()); } }; // MSG_REVIEW, MSG_PRODUCT and MSG_TABLE no longer have a handler, a producer // or a store -- the marketplace they belonged to is gone. They stay in the // enum, and their names stay in ppszTypeName below, because CInv serialises // `type` as a plain integer: dropping them would renumber nothing today but // would make it tempting to renumber later, and MSG_TX and MSG_BLOCK are wire // values shared with every other node. Reserved, never emitted, never served. enum { MSG_TX = 1, MSG_BLOCK, MSG_REVIEW, // reserved, dead MSG_PRODUCT, // reserved, dead MSG_TABLE, // reserved, dead }; static const char* ppszTypeName[] = { "ERROR", "tx", "block", "review", "product", "table", }; class CInv { public: int type; uint256 hash; CInv() { type = 0; hash = 0; } CInv(int typeIn, const uint256& hashIn) { type = typeIn; hash = hashIn; } CInv(const string& strType, const uint256& hashIn) { int i; for (i = 1; i < ARRAYLEN(ppszTypeName); i++) { if (strType == ppszTypeName[i]) { type = i; break; } } if (i == ARRAYLEN(ppszTypeName)) throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str())); hash = hashIn; } IMPLEMENT_SERIALIZE ( READWRITE(type); READWRITE(hash); ) friend inline bool operator<(const CInv& a, const CInv& b) { return (a.type < b.type || (a.type == b.type && a.hash < b.hash)); } bool IsKnownType() const { return (type >= 1 && type < ARRAYLEN(ppszTypeName)); } const char* GetCommand() const { if (!IsKnownType()) // Was "type=% unknown type": the % swallowed the space as a flag and // the u as the conversion, so this read "type= 3nknown type". throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type)); return ppszTypeName[type]; } string ToString() const { return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,14).c_str()); } void print() const { if (LogAcceptsCategory("net")) printf("CInv(%s)\n", ToString().c_str()); } }; // CRequestTracker and the PushRequest/"reply" round trip lived here. Nothing // in this tree ever called PushRequest, so the table was always empty and the // "reply" handler was pure inbound parser. Both removed. extern bool fClient; extern uint64 nLocalServices; extern CAddress addrLocalHost; extern unsigned short nListenPort; extern CNode* pnodeLocalHost; extern bool fShutdown; extern array vfThreadRunning; extern vector vNodes; extern CCriticalSection cs_vNodes; extern map mapRelay; extern deque > vRelayExpiration; extern CCriticalSection cs_mapRelay; extern map mapAlreadyAskedFor; class CNode { public: // socket uint64 nServices; SOCKET hSocket; CDataStream vSend; CDataStream vRecv; CCriticalSection cs_vSend; CCriticalSection cs_vRecv; unsigned int nPushPos; CAddress addr; int nVersion; bool fClient; bool fInbound; bool fNetworkNode; bool fDisconnect; protected: int nRefCount; public: int64 nReleaseTime; int64 nDisconnectSince; // inventory based relay set setInventoryKnown; set setInventoryKnown2; vector vInventoryToSend; CCriticalSection cs_inventory; multimap mapAskFor; // Last "btfpeers" we accepted from this node, to rate-limit the exchange. int64 nLastPexRecv; // Last getblocks we sent this peer, so we do not ask the same question // over and over. See CNode::PushGetBlocks. CBlockIndex* pindexLastGetBlocksBegin; uint256 hashLastGetBlocksEnd; // Liveness. A peer whose network path dies silently -- NAT drops an idle // mapping, a relay restarts, a route changes -- never sends FIN, so the // socket stays readable-never and the node simply stops hearing from it // with no error anywhere. These stamps are the only way to tell that // apart from a peer that merely has nothing to say. int64 nTimeConnected; int64 nLastSend; int64 nLastRecv; int64 nLastSendEmpty; string strBtfAddr; string strBtfMeeting; // When this peer's message loop last rewound a header without having made // progress, or 0 when it is not waiting, plus how much was buffered then. // The pair times a STALL rather than a duration, so a large message // arriving slowly is never mistaken for one that is never arriving. // See ProcessMessages. int64 nMsgWaitSince; unsigned int nMsgWaitSize; // Height this peer announced in its version message, or -1 if it sent a // version message that predates the field. Knowing how far along everyone // else is, is the only way a node can tell "in sync" from "not hearing". int nStartingHeight; CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) { nServices = 0; hSocket = hSocketIn; vSend.SetType(SER_NETWORK); vRecv.SetType(SER_NETWORK); nPushPos = -1; addr = addrIn; nVersion = 0; fClient = false; // set by version message fInbound = fInboundIn; fNetworkNode = false; fDisconnect = false; nRefCount = 0; nReleaseTime = 0; nDisconnectSince = 0; nLastPexRecv = 0; pindexLastGetBlocksBegin = NULL; hashLastGetBlocksEnd = 0; nTimeConnected = GetTime(); nLastSend = 0; nLastRecv = 0; nLastSendEmpty = GetTime(); strBtfAddr.clear(); strBtfMeeting.clear(); // Not waiting on anything yet. Left indeterminate, the first partial // message this peer sends is measured against whatever was in this // memory, and ProcessMessages drops it as unreadable on first contact. nMsgWaitSince = 0; nMsgWaitSize = 0; nStartingHeight = -1; // Push a version message /// when NTP implemented, change to just nTime = GetAdjustedTime() int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); // nBestHeight goes last so a node that predates it stops reading after // addr and treats the rest as trailing bytes, which cost it a log line // and nothing else. PushMessage("version", VERSION, nLocalServices, nTime, addr, nBestHeight); } // Disconnect() closes the socket and sets this to INVALID_SOCKET, so by the // time a node is deleted there is normally nothing left to do here. It used // not to: Disconnect() closed the handle and left the number in place, and // this destructor closed that same number a second time -- with a raw // closesocket() that the socket accounting never saw, so neither the double // close nor the stale claim showed up in any report. // // A double close is not a harmless no-op. Between the two, the operating // system is free to hand that number to a new socket -- this node opens // hundreds a minute -- and the second close then takes down a connection // that belongs to somebody else, which the log can only report as a peer // vanishing for no reason. `dropping node: its socket is no longer valid` // is what that looks like from the outside. ~CNode() { if (hSocket != INVALID_SOCKET) { // Route through BtfCloseSocket so the accounting sees this close. // A raw closesocket() here was invisible to sockcount, which is // why the leak numbers never added up, and leaving the descriptor // set afterwards is how a number that now belongs to somebody else // gets closed a second time. (#103) BtfCloseSocket(hSocket); hSocket = INVALID_SOCKET; } } private: CNode(const CNode&); void operator=(const CNode&); public: bool ReadyToDisconnect() { return fDisconnect || GetRefCount() <= 0; } int GetRefCount() { return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0); } void AddRef(int64 nTimeout=0) { if (nTimeout != 0) nReleaseTime = max(nReleaseTime, GetTime() + nTimeout); else nRefCount++; } void Release() { nRefCount--; } void AddInventoryKnown(const CInv& inv) { CRITICAL_BLOCK(cs_inventory) setInventoryKnown.insert(inv); } void PushInventory(const CInv& inv) { CRITICAL_BLOCK(cs_inventory) if (!setInventoryKnown.count(inv)) vInventoryToSend.push_back(inv); } void AskFor(const CInv& inv) { // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent int64& nRequestTime = mapAlreadyAskedFor[inv]; if (LogAcceptsCategory("net")) printf("askfor %s %lld\n", inv.ToString().c_str(), nRequestTime); // Make sure not to reuse time indexes to keep things in the same order int64 nNow = (GetTime() - 1) * 1000000; static int64 nLastTime; nLastTime = nNow = max(nNow, ++nLastTime); // Each retry is 2 minutes after the last -- and because nRequestTime // is shared across peers, the same spacing is what strings requests // for one inv across its announcers. For transactions that is pacing; // for a new block it was the stall of issue #33: nine peers announce // the block, the first one asked does not serve it, and the ninth // candidate is not even asked until sixteen minutes in, with the pool // mining on the stale tip the whole time. // // Blocks retry on the fetch timescale, but only while we are at the // tip. That is where the stall costs something -- the pool keeps // handing out jobs against a dead tip -- and it is also where the // spacing is nearly free: one block is in flight, and its body has // almost always arrived before the second announcer's turn comes // round, so AlreadyHave drops the duplicate before a getdata is sent. // // While catching up neither half holds. A peer working through a // 500-deep queue can be minutes away from block N without anything // being wrong, so at 15s the second announcer is asked at +15s, the // third at +30s, and the bulk download arrives once per announcer -- // up to eight times over. Nothing caps that: the eight-entry cap is on // mapBlockFetch, which is a different mechanism from this spacing. // Two minutes is the right number there, and it is what this line did // before. Failover at the tip does not depend on this being 15s in any // case: mapBlockFetch re-issues a stalled getdata to the next peer on // its own timer, which is what actually fixes #33. bool fFast = (inv.type == MSG_BLOCK && IsBlockFetchNearTip()); int64 nRetryUsecs = (fFast ? BLOCK_FETCH_RETRY_SECS : 2 * 60) * 1000000LL; nRequestTime = max(nRequestTime + nRetryUsecs, nNow); mapAskFor.insert(make_pair(nRequestTime, inv)); } // "sending: tx (N bytes)" alone was ~71% of a 13-hour production // debug.log (issue #35), so tx sends are demoted to the /debugrelay-gated // "relay" category; every other command's send trace stays on "net". // The line is emitted in pieces across BeginMessage/EndMessage/ // AbortMessage, so all three must agree on the category or orphaned // "(N bytes)" fragments would leak into a plain -debug log. // Valid only mid-message (nPushPos != -1). const char* SendLogCategory() const { return strcmp(GetMessageCommand(), "tx") == 0 ? "relay" : "net"; } void BeginMessage(const char* pszCommand) { EnterCriticalSection(&cs_vSend); if (nPushPos != -1) AbortMessage(); nPushPos = vSend.size(); vSend << CMessageHeader(pszCommand, 0); if (LogAcceptsCategory(SendLogCategory())) printf("sending: %-12s ", pszCommand); } void AbortMessage() { if (nPushPos == -1) return; // Capture before nPushPos is cleared; GetMessageCommand() needs it. const char* pszCategory = SendLogCategory(); vSend.resize(nPushPos); nPushPos = -1; LeaveCriticalSection(&cs_vSend); if (LogAcceptsCategory(pszCategory)) printf("(aborted)\n"); } void EndMessage() { extern int nDropMessagesTest; if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) { // Same category as the "sending: " this line interrupts, so a tx // does not announce its own drop under "net" having been gated // off under "relay". nPushPos can be -1 here, and then // GetMessageCommand() returns "" and this is "net" as before. if (LogAcceptsCategory(SendLogCategory())) printf("dropmessages DROPPING SEND MESSAGE\n"); AbortMessage(); return; } if (nPushPos == -1) return; // Patch in the size unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); if (LogAcceptsCategory(SendLogCategory())) printf("(%d bytes) ", nSize); //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++) // printf("%02x ", vSend[i] & 0xff); if (LogAcceptsCategory(SendLogCategory())) printf("\n"); nPushPos = -1; LeaveCriticalSection(&cs_vSend); } void EndMessageAbortIfEmpty() { if (nPushPos == -1) return; int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); if (nSize > 0) EndMessage(); else AbortMessage(); } const char* GetMessageCommand() const { if (nPushPos == -1) return ""; return &vSend[nPushPos] + offsetof(CMessageHeader, pchCommand); } // Ask this peer to fill in blocks we are missing, but only once per // question. // // Every orphan block fires one of these, and an inv for a block we already // hold as an orphan fires another. A node that is missing part of the // chain therefore asks the same peer the same thing repeatedly: measured // on a production node, 1287 orphan blocks out of 4117 processed, and 97 // "already have block" from the answers coming back more than once. The // duplicate answers create more orphans, which fire more requests. // // Remembering the last question asked breaks that loop. Same fix Bitcoin // made in e2c2648c1. // Body lives in net.cpp: it builds a CBlockLocator, which main.h defines, // and main.h is included after this file. void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd); void PushMessage(const char* pszCommand) { try { BeginMessage(pszCommand); EndMessage(); } catch (...) { AbortMessage(); throw; } } template void PushMessage(const char* pszCommand, const T1& a1) { try { BeginMessage(pszCommand); vSend << a1; EndMessage(); } catch (...) { AbortMessage(); throw; } } template void PushMessage(const char* pszCommand, const T1& a1, const T2& a2) { try { BeginMessage(pszCommand); vSend << a1 << a2; EndMessage(); } catch (...) { AbortMessage(); throw; } } template void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3) { try { BeginMessage(pszCommand); vSend << a1 << a2 << a3; EndMessage(); } catch (...) { AbortMessage(); throw; } } template void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4) { try { BeginMessage(pszCommand); vSend << a1 << a2 << a3 << a4; EndMessage(); } catch (...) { AbortMessage(); throw; } } template void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5) { try { BeginMessage(pszCommand); vSend << a1 << a2 << a3 << a4 << a5; EndMessage(); } catch (...) { AbortMessage(); throw; } } void Disconnect(); }; inline void RelayInventory(const CInv& inv) { // Put on lists to offer to the other nodes CRITICAL_BLOCK(cs_vNodes) foreach(CNode* pnode, vNodes) pnode->PushInventory(inv); } template void RelayMessage(const CInv& inv, const T& a) { CDataStream ss(SER_NETWORK); ss.reserve(10000); ss << a; RelayMessage(inv, ss); } template<> inline void RelayMessage<>(const CInv& inv, const CDataStream& ss) { CRITICAL_BLOCK(cs_mapRelay) { // Expire old relay messages while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) { mapRelay.erase(vRelayExpiration.front().second); vRelayExpiration.pop_front(); } // Save original serialized message so newer versions are preserved mapRelay[inv] = ss; vRelayExpiration.push_back(make_pair(GetTime() + 15 * 60, inv)); } RelayInventory(inv); } // The publish/subscribe advert templates that used to close this file // (AdvertStartPublish / AdvertStopPublish / AdvertRemoveSource) are gone along // with the marketplace objects they carried. Nothing ever handled an inbound // "publish" or "pub-cancel", so the machinery only ever pushed; what it pushed // was CProduct, which no longer exists.