From 42605ce8bcc9bd01b86491c74fee14de77960868 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Wed, 26 May 2010 00:05:26 +0000 Subject: [PATCH] better prevention of inventory relaying during initial download, message checksum between nodes with 0.2.9 or higher, optimization level up from -O0 to -O2, rpc functions: setlabel, getlabel, getaddressesbylabel, getreceivedbyaddress, getreceivedbylabel, listreceivedbyaddress, listreceivedbylabel -- version 0.2.9 git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@78 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- db.h | 2 + init.cpp | 7 +- main.cpp | 76 +++++++----- makefile.mingw | 2 +- makefile.unix | 2 +- net.h | 30 ++++- rpc.cpp | 305 ++++++++++++++++++++++++++++++++++++++++--------- serialize.h | 14 ++- ui.cpp | 9 +- ui.h | 9 ++ uibase.h | 2 +- uiproject.fbp | 2 +- util.cpp | 5 - 13 files changed, 364 insertions(+), 101 deletions(-) diff --git a/db.h b/db.h index fb4e9268..0b778d5f 100644 --- a/db.h +++ b/db.h @@ -328,6 +328,8 @@ public: bool EraseName(const string& strAddress) { + // This should only be used for sending addresses, never for receiving addresses, + // receiving addresses must always have an address book entry if they're not change return. CRITICAL_BLOCK(cs_mapAddressBook) mapAddressBook.erase(strAddress); nWalletDBUpdated++; diff --git a/init.cpp b/init.cpp index db8886e1..833a8a3f 100644 --- a/init.cpp +++ b/init.cpp @@ -224,9 +224,6 @@ bool CMyApp::Initialize(int& argc, wxChar** argv) } } - if (fDaemon) - fprintf(stdout, "bitcoin server starting\n"); - #ifdef __WXGTK__ if (fDaemon || fCommandLine) { @@ -447,7 +444,8 @@ bool CMyApp::OnInit2() // // Load data files // - bool fFirstRun; + if (fDaemon) + fprintf(stdout, "bitcoin server starting\n"); strErrors = ""; int64 nStart; @@ -465,6 +463,7 @@ bool CMyApp::OnInit2() printf("Loading wallet...\n"); nStart = GetTimeMillis(); + bool fFirstRun; if (!LoadWallet(fFirstRun)) strErrors += _("Error loading wallet.dat \n"); printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart); diff --git a/main.cpp b/main.cpp index ad0208a2..05a182c1 100644 --- a/main.cpp +++ b/main.cpp @@ -1336,19 +1336,12 @@ bool CBlock::AcceptBlock() if (!AddToBlockIndex(nFile, nBlockPos)) return error("AcceptBlock() : AddToBlockIndex failed"); - // Don't relay old inventory during initial block download. - // Please keep this number updated to a few thousand below current block count. - if (hashBestChain == hash && nBestHeight > 55000) - RelayInventory(CInv(MSG_BLOCK, hash)); - - // // Add atoms to user reviews for coins created - // vector vchPubKey; - // if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey)) - // { - // unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100; - // vector vAtoms(1, nAtom); - // AddAtomsAndPropagate(Hash(vchPubKey.begin(), vchPubKey.end()), vAtoms, true); - // } + // Relay inventory, but don't relay old inventory during initial block download + if (hashBestChain == hash) + CRITICAL_BLOCK(cs_vNodes) + foreach(CNode* pnode, vNodes) + if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 55000)) + pnode->PushInventory(CInv(MSG_BLOCK, hash)); return true; } @@ -1721,6 +1714,7 @@ bool ProcessMessages(CNode* pfrom) // (4) message start // (12) command // (4) size + // (4) checksum // (x) data // @@ -1728,12 +1722,13 @@ bool ProcessMessages(CNode* pfrom) { // Scan for message start CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart)); - if (vRecv.end() - pstart < sizeof(CMessageHeader)) + int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader()); + if (vRecv.end() - pstart < nHeaderSize) { - if (vRecv.size() > sizeof(CMessageHeader)) + if (vRecv.size() > nHeaderSize) { printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n"); - vRecv.erase(vRecv.begin(), vRecv.end() - sizeof(CMessageHeader)); + vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize); } break; } @@ -1742,6 +1737,7 @@ bool ProcessMessages(CNode* pfrom) vRecv.erase(vRecv.begin(), pstart); // Read header + vector vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize); CMessageHeader hdr; vRecv >> hdr; if (!hdr.IsValid()) @@ -1757,10 +1753,9 @@ bool ProcessMessages(CNode* pfrom) { // Rewind and wait for rest of message ///// need a mechanism to give up waiting for overlong message size error - //if (fDebug) - // printf("message-break\n"); - vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr)); - Sleep(100); + if (fDebug) + printf("message-break\n"); + vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end()); break; } @@ -1768,6 +1763,20 @@ bool ProcessMessages(CNode* pfrom) CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion); vRecv.ignore(nMessageSize); + // Checksum + if (vRecv.GetVersion() >= 209) + { + uint256 hash = Hash(vMsg.begin(), vMsg.end()); + unsigned int nChecksum = 0; + memcpy(&nChecksum, &hash, sizeof(nChecksum)); + if (nChecksum != hdr.nChecksum) + { + printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", + strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum); + continue; + } + } + // Process message bool fRet = false; try @@ -1844,6 +1853,9 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) vRecv >> addrFrom >> nNonce; if (pfrom->nVersion >= 106 && !vRecv.empty()) vRecv >> strSubVer; + if (pfrom->nVersion >= 209 && !vRecv.empty()) + vRecv >> pfrom->nStartingHeight; + if (pfrom->nVersion == 0) return false; @@ -1854,9 +1866,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return true; } - pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION)); - pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION)); - pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); if (pfrom->fClient) { @@ -1866,6 +1875,13 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) AddTimeData(pfrom->addr.ip, nTime); + // Change version + if (pfrom->nVersion >= 209) + pfrom->PushMessage("verack"); + pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION)); + if (pfrom->nVersion < 209) + pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION)); + // Ask the first connected node for block updates static bool fAskedForBlocks; if (!fAskedForBlocks && !pfrom->fClient) @@ -1876,7 +1892,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->fSuccessfullyConnected = true; - printf("version message: version %d\n", pfrom->nVersion); + printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight); } @@ -1887,6 +1903,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } + else if (strCommand == "verack") + { + pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION)); + } + + else if (strCommand == "addr") { vector vAddr; @@ -2101,9 +2123,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) vRecv >> *pblock; //// debug print - // printf("received block:\n"); - // pblock->print(); printf("received block %s\n", pblock->GetHash().ToString().substr(0,16).c_str()); + // pblock->print(); CInv inv(MSG_BLOCK, pblock->GetHash()); pfrom->AddInventoryKnown(inv); @@ -2388,8 +2409,11 @@ void GenerateBitcoins(bool fGenerate) int nAddThreads = nProcessors - vnThreadsRunning[3]; printf("Starting %d BitcoinMiner threads\n", nAddThreads); for (int i = 0; i < nAddThreads; i++) + { if (!CreateThread(ThreadBitcoinMiner, NULL)) printf("Error: CreateThread(ThreadBitcoinMiner) failed\n"); + Sleep(10); + } } } diff --git a/makefile.mingw b/makefile.mingw index 449a9607..ee63d11e 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -29,7 +29,7 @@ LIBS= \ WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH DEBUGFLAGS=-g -D__WXDEBUG__ -CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS) +CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS) HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \ script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h diff --git a/makefile.unix b/makefile.unix index 10c4eece..e7729adc 100644 --- a/makefile.unix +++ b/makefile.unix @@ -29,7 +29,7 @@ LIBS= \ WXDEFS=-D__WXGTK__ -DNOPCH DEBUGFLAGS=-g -D__WXDEBUG__ -CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS) +CFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS) HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \ script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h diff --git a/net.h b/net.h index 1593a975..46344ed9 100644 --- a/net.h +++ b/net.h @@ -8,6 +8,7 @@ class CInv; class CRequestTracker; class CNode; class CBlockIndex; +extern int nBestHeight; @@ -59,7 +60,7 @@ public: char pchMessageStart[sizeof(::pchMessageStart)]; char pchCommand[COMMAND_SIZE]; unsigned int nMessageSize; - //unsigned int nChecksum; + unsigned int nChecksum; CMessageHeader() { @@ -67,7 +68,7 @@ public: memset(pchCommand, 0, sizeof(pchCommand)); pchCommand[1] = 1; nMessageSize = -1; - //nChecksum = 0; + nChecksum = 0; } CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) @@ -75,6 +76,7 @@ public: memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); strncpy(pchCommand, pszCommand, COMMAND_SIZE); nMessageSize = nMessageSizeIn; + nChecksum = 0; } IMPLEMENT_SERIALIZE @@ -82,8 +84,8 @@ public: READWRITE(FLATDATA(pchMessageStart)); READWRITE(FLATDATA(pchCommand)); READWRITE(nMessageSize); - //if (nVersion >= 209 && GetCommand() != "version") - // READWRITE(nChecksum); + if (nVersion >= 209) + READWRITE(nChecksum); ) string GetCommand() @@ -475,6 +477,7 @@ extern CAddress addrProxy; + class CNode { public: @@ -507,6 +510,7 @@ public: uint256 hashContinue; CBlockIndex* pindexLastGetBlocksBegin; uint256 hashLastGetBlocksEnd; + int nStartingHeight; // flood vector vAddrToSend; @@ -529,7 +533,9 @@ public: nServices = 0; hSocket = hSocketIn; vSend.SetType(SER_NETWORK); + vSend.SetVersion(0); vRecv.SetType(SER_NETWORK); + vRecv.SetVersion(0); nLastSend = 0; nLastRecv = 0; nLastSendEmpty = GetTime(); @@ -548,6 +554,7 @@ public: hashContinue = 0; pindexLastGetBlocksBegin = 0; hashLastGetBlocksEnd = 0; + nStartingHeight = -1; fGetAddr = false; nNextSendTxInv = 0; vfSubscribe.assign(256, false); @@ -558,7 +565,8 @@ public: CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr); CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost); RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); - PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, string(pszSubVer)); + PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, + nLocalHostNonce, string(pszSubVer), nBestHeight); } ~CNode() @@ -680,10 +688,20 @@ public: if (nHeaderStart == -1) return; - // Patch in the size + // Set the size unsigned int nSize = vSend.size() - nMessageStart; memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); + // Set the checksum + if (vSend.GetVersion() >= 209) + { + uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end()); + unsigned int nChecksum = 0; + memcpy(&nChecksum, &hash, sizeof(nChecksum)); + assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum)); + memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum)); + } + printf("(%d bytes) ", nSize); printf("\n"); diff --git a/rpc.cpp b/rpc.cpp index c56ce263..d988786e 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -26,7 +26,7 @@ void ThreadRPCServer2(void* parg); /// -/// Note: I'm not finished designing this interface, it's still subject to change. +/// Note: This interface may still be subject to change. /// @@ -188,6 +188,73 @@ Value getnewaddress(const Array& params) } +Value setlabel(const Array& params) +{ + if (params.size() < 1 || params.size() > 2) + throw runtime_error( + "setlabel