From f03304a9c79a6cc6096ed501ad38702fd012e7f7 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Sun, 5 Dec 2010 09:29:30 +0000 Subject: [PATCH] preps for future client-only mode, jgarzik's initial download speedup git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@195 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- db.cpp | 2 ++ db.h | 2 +- irc.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 75 ++++++++++++++++++++++++++++++++++++++-------------- main.h | 37 ++++++++++++++++++++------ serialize.h | 2 +- 6 files changed, 165 insertions(+), 29 deletions(-) diff --git a/db.cpp b/db.cpp index 40998fb74..fb4e48c59 100644 --- a/db.cpp +++ b/db.cpp @@ -132,6 +132,8 @@ void CDB::Close() // Flush database activity from memory pool to disk log unsigned int nMinutes = 0; + if (fReadOnly) + nMinutes = 1; if (strFile == "addr.dat") nMinutes = 2; if (strFile == "blkindex.dat" && IsInitialBlockDownload() && nBestHeight % 500 != 0) diff --git a/db.h b/db.h index e3ffc40c6..72fe0d9fa 100644 --- a/db.h +++ b/db.h @@ -265,7 +265,7 @@ public: class CTxDB : public CDB { public: - CTxDB(const char* pszMode="r+") : CDB(!fClient ? "blkindex.dat" : NULL, pszMode) { } + CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { } private: CTxDB(const CTxDB&); void operator=(const CTxDB&); diff --git a/irc.cpp b/irc.cpp index 55b23f2de..1734d76fa 100644 --- a/irc.cpp +++ b/irc.cpp @@ -173,6 +173,68 @@ bool Wait(int nSeconds) return true; } +bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet) +{ + strRet.clear(); + loop + { + string strLine; + if (!RecvLineIRC(hSocket, strLine)) + return false; + + vector vWords; + ParseString(strLine, ' ', vWords); + if (vWords.size() < 2) + continue; + + if (vWords[1] == psz1) + { + printf("IRC %s\n", strLine.c_str()); + strRet = strLine; + return true; + } + } +} + +bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet) +{ + Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str()); + + string strLine; + if (!RecvCodeLine(hSocket, "302", strLine)) + return false; + + vector vWords; + ParseString(strLine, ' ', vWords); + if (vWords.size() < 4) + return false; + + string str = vWords[3]; + if (str.rfind("@") == string::npos) + return false; + string strHost = str.substr(str.rfind("@")+1); + + unsigned int a=0, b=0, c=0, d=0; + if (sscanf(strHost.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) == 4 && + inet_addr(strHost.c_str()) != INADDR_NONE) + { + printf("GetIPFromIRC() userhost is IP %s\n", strHost.c_str()); + ipRet = CAddress(strHost).ip; + } + else + { + printf("GetIPFromIRC() got userhost %s\n", strHost.c_str()); + if (fUseProxy) + return false; + struct hostent* phostent = gethostbyname(strHost.c_str()); + if (!phostent || !phostent->h_addr_list || !phostent->h_addr_list[0]) + return false; + ipRet = *(u_long*)phostent->h_addr_list[0]; + } + + return true; +} + void ThreadIRCSeed(void* parg) @@ -265,6 +327,20 @@ void ThreadIRCSeed2(void* parg) } Sleep(500); + // Get my external IP from IRC server + CAddress addrFromIRC; + if (GetIPFromIRC(hSocket, strMyName, addrFromIRC.ip)) + { + // Just using it as a backup for now + printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToStringIP().c_str()); + if (addrFromIRC.IsRoutable() && !fUseProxy && !addrLocalHost.IsRoutable()) + { + addrLocalHost.ip = addrFromIRC.ip; + strMyName = EncodeAddress(addrLocalHost); + Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); + } + } + Send(hSocket, fTestNet ? "JOIN #bitcoinTEST\r" : "JOIN #bitcoin\r"); Send(hSocket, fTestNet ? "WHO #bitcoinTEST\r" : "WHO #bitcoin\r"); diff --git a/main.cpp b/main.cpp index f4131395f..be29ceb97 100644 --- a/main.cpp +++ b/main.cpp @@ -870,6 +870,11 @@ void ResendWalletTransactions() bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) { + if (!fReadTransactions) + { + *this = pindex->GetBlockHeader(); + return true; + } if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions)) return false; if (GetHash() != pindex->GetBlockHash()) @@ -1425,7 +1430,10 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork(); CTxDB txdb; + txdb.TxnBegin(); txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); + if (!txdb.TxnCommit()) + return false; // New best if (pindexNew->bnChainWork > bnBestChainWork) @@ -1529,9 +1537,9 @@ bool CBlock::AcceptBlock() // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK))) return error("AcceptBlock() : out of disk space"); - unsigned int nFile; - unsigned int nBlockPos; - if (!WriteToDisk(!fClient, nFile, nBlockPos)) + unsigned int nFile = -1; + unsigned int nBlockPos = 0; + if (!WriteToDisk(nFile, nBlockPos)) return error("AcceptBlock() : WriteToDisk failed"); if (!AddToBlockIndex(nFile, nBlockPos)) return error("AcceptBlock() : AddToBlockIndex failed"); @@ -1777,7 +1785,7 @@ bool LoadBlockIndex(bool fAllowNew) // Start new block file unsigned int nFile; unsigned int nBlockPos; - if (!block.WriteToDisk(!fClient, nFile, nBlockPos)) + if (!block.WriteToDisk(nFile, nBlockPos)) return error("LoadBlockIndex() : writing genesis block to disk failed"); if (!block.AddToBlockIndex(nFile, nBlockPos)) return error("LoadBlockIndex() : genesis block not accepted"); @@ -2181,11 +2189,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); - if (pfrom->fClient) - { - pfrom->vSend.nType |= SER_BLOCKHEADERONLY; - pfrom->vRecv.nType |= SER_BLOCKHEADERONLY; - } AddTimeData(pfrom->addr.ip, nTime); @@ -2359,9 +2362,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) map::iterator mi = mapBlockIndex.find(inv.hash); if (mi != mapBlockIndex.end()) { - //// could optimize this to send header straight from blockindex for client CBlock block; - block.ReadFromDisk((*mi).second, !pfrom->fClient); + block.ReadFromDisk((*mi).second); pfrom->PushMessage("block", block); // Trigger them to send a getblocks request for the next batch of inventory @@ -2405,7 +2407,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) uint256 hashStop; vRecv >> locator >> hashStop; - // Find the first block the caller has in the main chain + // Find the last block the caller has in the main chain CBlockIndex* pindex = locator.GetBlockIndex(); // Send the rest of the chain @@ -2433,6 +2435,42 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } + else if (strCommand == "getheaders") + { + CBlockLocator locator; + uint256 hashStop; + vRecv >> locator >> hashStop; + + CBlockIndex* pindex = NULL; + if (locator.IsNull()) + { + // If locator is null, return the hashStop block + map::iterator mi = mapBlockIndex.find(hashStop); + if (mi == mapBlockIndex.end()) + return true; + pindex = (*mi).second; + } + else + { + // Find the last block the caller has in the main chain + pindex = locator.GetBlockIndex(); + if (pindex) + pindex = pindex->pnext; + } + + vector vHeaders; + int nLimit = 2000 + locator.GetDistanceBack(); + printf("getheaders %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit); + for (; pindex; pindex = pindex->pnext) + { + vHeaders.push_back(pindex->GetBlockHeader()); + if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop) + break; + } + pfrom->PushMessage("headers", vHeaders); + } + + else if (strCommand == "tx") { vector vWorkQueue; @@ -2488,17 +2526,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) else if (strCommand == "block") { - auto_ptr pblock(new CBlock); - vRecv >> *pblock; + CBlock block; + vRecv >> block; - //// debug print - printf("received block %s\n", pblock->GetHash().ToString().substr(0,20).c_str()); - // pblock->print(); + printf("received block %s\n", block.GetHash().ToString().substr(0,20).c_str()); + // block.print(); - CInv inv(MSG_BLOCK, pblock->GetHash()); + CInv inv(MSG_BLOCK, block.GetHash()); pfrom->AddInventoryKnown(inv); - if (ProcessBlock(pfrom, pblock.get())) + if (ProcessBlock(pfrom, &block)) mapAlreadyAskedFor.erase(inv); } diff --git a/main.h b/main.h index 2c24eba2d..cca233896 100644 --- a/main.h +++ b/main.h @@ -865,11 +865,6 @@ public: return nChangeCached; } - bool IsFromMe() const - { - return (GetDebit() > 0); - } - void GetAccountAmounts(string strAccount, const set& setPubKey, int64& nGenerated, int64& nReceived, int64& nSent, int64& nFee) const { @@ -901,6 +896,11 @@ public: } } + bool IsFromMe() const + { + return (GetDebit() > 0); + } + bool IsConfirmed() const { // Quick answer in most cases @@ -1158,14 +1158,12 @@ public: } - bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet) + bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet) { // Open history file to append CAutoFile fileout = AppendBlockFile(nFileRet); if (!fileout) return error("CBlock::WriteToDisk() : AppendBlockFile failed"); - if (!fWriteTransactions) - fileout.nType |= SER_BLOCKHEADERONLY; // Write index header unsigned int nSize = fileout.GetSerializeSize(*this); @@ -1310,6 +1308,19 @@ public: nNonce = block.nNonce; } + CBlock GetBlockHeader() const + { + CBlock block; + block.nVersion = nVersion; + if (pprev) + block.hashPrevBlock = pprev->GetBlockHash(); + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block; + } + uint256 GetBlockHash() const { return *phashBlock; @@ -1511,6 +1522,16 @@ public: READWRITE(vHave); ) + void SetNull() + { + vHave.clear(); + } + + bool IsNull() + { + return vHave.empty(); + } + void Set(const CBlockIndex* pindex) { vHave.clear(); diff --git a/serialize.h b/serialize.h index 5088e3700..7f47d0fcb 100644 --- a/serialize.h +++ b/serialize.h @@ -25,7 +25,7 @@ class CDataStream; class CAutoFile; static const unsigned int MAX_SIZE = 0x02000000; -static const int VERSION = 31702; +static const int VERSION = 31703; static const char* pszSubVer = "";