diff --git a/db.cpp b/db.cpp index 9657cbf98..84b294c38 100644 --- a/db.cpp +++ b/db.cpp @@ -503,6 +503,11 @@ bool CAddrDB::WriteAddress(const CAddress& addr) return Write(make_pair(string("addr"), addr.GetKey()), addr); } +bool CAddrDB::EraseAddress(const CAddress& addr) +{ + return Erase(make_pair(string("addr"), addr.GetKey())); +} + bool CAddrDB::LoadAddresses() { CRITICAL_BLOCK(cs_mapAddresses) @@ -554,11 +559,6 @@ bool CAddrDB::LoadAddresses() pcursor->close(); printf("Loaded %d addresses\n", mapAddresses.size()); - - // Fix for possible bug that manifests in mapAddresses.count in irc.cpp, - // just need to call count here and it doesn't happen there. The bug was the - // pack pragma in irc.cpp and has been fixed, but I'm not in a hurry to delete this. - mapAddresses.count(vector(18)); } return true; diff --git a/db.h b/db.h index 3452dd89f..a0054aa13 100644 --- a/db.h +++ b/db.h @@ -298,6 +298,7 @@ private: void operator=(const CAddrDB&); public: bool WriteAddress(const CAddress& addr); + bool EraseAddress(const CAddress& addr); bool LoadAddresses(); }; diff --git a/irc.cpp b/irc.cpp index 4c839c421..e246fcd10 100644 --- a/irc.cpp +++ b/irc.cpp @@ -84,18 +84,31 @@ bool RecvLine(SOCKET hSocket, string& strLine) } else if (nBytes <= 0) { + if (fShutdown) + return false; + if (nBytes < 0) + { + int nErr = WSAGetLastError(); + if (nErr == WSAEMSGSIZE) + continue; + if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS) + { + Sleep(10); + continue; + } + } if (!strLine.empty()) return true; - // socket closed - printf("IRC socket closed\n"); - return false; - } - else - { - // socket error - int nErr = WSAGetLastError(); - if (nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) + if (nBytes == 0) + { + // socket closed + printf("IRC socket closed\n"); + return false; + } + else { + // socket error + int nErr = WSAGetLastError(); printf("IRC recv failed: %d\n", nErr); return false; } @@ -293,8 +306,8 @@ void ThreadIRCSeed2(void* parg) CAddress addr; if (DecodeAddress(pszName, addr)) { - addr.nTime = GetAdjustedTime() - 51 * 60; - if (AddAddress(addr)) + addr.nTime = GetAdjustedTime(); + if (AddAddress(addr, 51 * 60)) printf("IRC got new address\n"); nGotIRCAddresses++; } diff --git a/main.cpp b/main.cpp index 764ddaac0..e18cdc4f1 100644 --- a/main.cpp +++ b/main.cpp @@ -929,7 +929,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) bool IsInitialBlockDownload() { - if (pindexBest == NULL) + if (pindexBest == NULL || nBestHeight < 74000) return true; static int64 nLastUpdate; static CBlockIndex* pindexLastBest; @@ -2172,6 +2172,24 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pfrom->nVersion < 209) pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION)); + if (!pfrom->fInbound) + { + // Advertise our address + if (addrLocalHost.IsRoutable() && !fUseProxy) + { + CAddress addr(addrLocalHost); + addr.nTime = GetAdjustedTime(); + pfrom->PushAddress(addr); + } + + // Get recent addresses + if (pfrom->nVersion >= 31402 || mapAddresses.size() < 1000) + { + pfrom->PushMessage("getaddr"); + pfrom->fGetAddr = true; + } + } + // Ask the first connected node for block updates static int nAskedForBlocks; if (!pfrom->fClient && (nAskedForBlocks < 1 || vNodes.size() <= 1)) @@ -2208,14 +2226,18 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { vector vAddr; vRecv >> vAddr; - if (pfrom->nVersion < 200) // don't want addresses from 0.1.5 + + // Don't want addr from older versions unless seeding + if (pfrom->nVersion < 209) return true; - if (pfrom->nVersion < 209 && mapAddresses.size() > 1000) // don't want addr from 0.2.0 unless seeding + if (pfrom->nVersion < 31402 && mapAddresses.size() > 1000) return true; if (vAddr.size() > 1000) return error("message addr size() = %d", vAddr.size()); // Store the new addresses + int64 nNow = GetAdjustedTime(); + int64 nSince = nNow - 10 * 60; foreach(CAddress& addr, vAddr) { if (fShutdown) @@ -2223,12 +2245,11 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // ignore IPv6 for now, since it isn't implemented anyway if (!addr.IsIPv4()) continue; - addr.nTime = GetAdjustedTime() - 2 * 60 * 60; - if (pfrom->fGetAddr || vAddr.size() > 10) - addr.nTime -= 5 * 24 * 60 * 60; - AddAddress(addr); + if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) + addr.nTime = nNow - 5 * 24 * 60 * 60; + AddAddress(addr, 2 * 60 * 60); pfrom->AddAddressKnown(addr); - if (!pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) + if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) { // Relay to a limited number of other nodes CRITICAL_BLOCK(cs_vNodes) @@ -2243,6 +2264,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) multimap mapMix; foreach(CNode* pnode, vNodes) { + if (pnode->nVersion < 31402) + continue; unsigned int nPointer; memcpy(&nPointer, &pnode, sizeof(nPointer)); uint256 hashKey = hashRand ^ nPointer; @@ -2610,9 +2633,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle) if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty()) pto->PushMessage("ping"); + // Resend wallet transactions that haven't gotten in a block yet + ResendWalletTransactions(); + // Address refresh broadcast static int64 nLastRebroadcast; - if (GetTime() - nLastRebroadcast > 24 * 60 * 60) // every 24 hours + if (GetTime() - nLastRebroadcast > 24 * 60 * 60) { nLastRebroadcast = GetTime(); CRITICAL_BLOCK(cs_vNodes) @@ -2624,13 +2650,42 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Rebroadcast our address if (addrLocalHost.IsRoutable() && !fUseProxy) - pnode->PushAddress(addrLocalHost); + { + CAddress addr(addrLocalHost); + addr.nTime = GetAdjustedTime(); + pnode->PushAddress(addr); + } } } } - // Resend wallet transactions that haven't gotten in a block yet - ResendWalletTransactions(); + // Clear out old addresses periodically so it's not too much work at once + static int64 nLastClear; + if (nLastClear == 0) + nLastClear = GetTime(); + if (GetTime() - nLastClear > 10 * 60 && vNodes.size() >= 3) + { + nLastClear = GetTime(); + CRITICAL_BLOCK(cs_mapAddresses) + { + CAddrDB addrdb; + int64 nSince = GetAdjustedTime() - 14 * 24 * 60 * 60; + for (map, CAddress>::iterator mi = mapAddresses.begin(); + mi != mapAddresses.end();) + { + const CAddress& addr = (*mi).second; + if (addr.nTime < nSince) + { + if (mapAddresses.size() < 1000 || GetTime() > nLastClear + 20) + break; + addrdb.EraseAddress(addr); + mapAddresses.erase(mi++); + } + else + mi++; + } + } + } // diff --git a/net.cpp b/net.cpp index 06a12d4fb..3890a7afc 100644 --- a/net.cpp +++ b/net.cpp @@ -144,7 +144,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha } } closesocket(hSocket); - if (strLine.find("<")) + if (strLine.find("<") != -1) strLine = strLine.substr(0, strLine.find("<")); strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); while (strLine.size() > 0 && isspace(strLine[strLine.size()-1])) @@ -224,12 +224,13 @@ bool GetMyExternalIP(unsigned int& ipRet) -bool AddAddress(CAddress addr) +bool AddAddress(CAddress addr, int64 nTimePenalty) { if (!addr.IsRoutable()) return false; if (addr.ip == addrLocalHost.ip) return false; + addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty); CRITICAL_BLOCK(cs_mapAddresses) { map, CAddress>::iterator it = mapAddresses.find(addr.GetKey()); @@ -1073,25 +1074,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect) return false; pnode->fNetworkNode = true; - if (addrLocalHost.IsRoutable() && !fUseProxy) - { - // Advertise our address - vector vAddr; - vAddr.push_back(addrLocalHost); - pnode->PushMessage("addr", vAddr); - } - - // Get as many addresses as we can - pnode->PushMessage("getaddr"); - pnode->fGetAddr = true; // don't relay the results of the getaddr - - ////// should the one on the receiving end do this too? - // Subscribe our local subscription list - const unsigned int nHops = 0; - for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++) - if (pnodeLocalHost->vfSubscribe[nChannel]) - pnode->PushMessage("subscribe", nChannel, nHops); - return true; } diff --git a/net.h b/net.h index 33c59147b..f07081619 100644 --- a/net.h +++ b/net.h @@ -24,7 +24,7 @@ enum bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet); bool GetMyExternalIP(unsigned int& ipRet); -bool AddAddress(CAddress addr); +bool AddAddress(CAddress addr, int64 nTimePenalty=0); void AddressCurrentlyConnected(const CAddress& addr); CNode* FindNode(unsigned int ip); CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0); @@ -139,7 +139,7 @@ public: unsigned int ip; unsigned short port; - // disk only + // disk and network only unsigned int nTime; // memory only @@ -186,7 +186,7 @@ public: memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); ip = INADDR_NONE; port = GetDefaultPort(); - nTime = GetAdjustedTime(); + nTime = 100000000; nLastTry = 0; } @@ -218,11 +218,12 @@ public: IMPLEMENT_SERIALIZE ( + if (fRead) + const_cast(this)->Init(); if (nType & SER_DISK) - { READWRITE(nVersion); + if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH))) READWRITE(nTime); - } READWRITE(nServices); READWRITE(FLATDATA(pchReserved)); // for IPv6 READWRITE(ip); @@ -415,7 +416,7 @@ public: const char* GetCommand() const { if (!IsKnownType()) - throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type)); + throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type)); return ppszTypeName[type]; } @@ -732,13 +733,6 @@ public: AbortMessage(); } - const char* GetMessageCommand() const - { - if (nHeaderStart == -1) - return ""; - return &vSend[nHeaderStart] + offsetof(CMessageHeader, pchCommand); - } - diff --git a/rpc.cpp b/rpc.cpp index ac413cf11..1df2238c9 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -656,6 +656,7 @@ Value backupwallet(const Array& params, bool fHelp) return Value::null; } + Value validateaddress(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) diff --git a/serialize.h b/serialize.h index 6b3b3b579..af45d898e 100644 --- a/serialize.h +++ b/serialize.h @@ -22,7 +22,7 @@ class CDataStream; class CAutoFile; static const unsigned int MAX_SIZE = 0x02000000; -static const int VERSION = 31401; +static const int VERSION = 31402; static const char* pszSubVer = "";