better prevention of inventory relaying during initial download,
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Wed, 26 May 2010 00:05:26 +0000 (00:05 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Wed, 26 May 2010 00:05:26 +0000 (00:05 +0000)
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

13 files changed:
db.h
init.cpp
main.cpp
makefile.mingw
makefile.unix
net.h
rpc.cpp
serialize.h
ui.cpp
ui.h
uibase.h
uiproject.fbp
util.cpp

diff --git a/db.h b/db.h
index fb4e926..0b778d5 100644 (file)
--- a/db.h
+++ b/db.h
@@ -328,6 +328,8 @@ public:
 \r
     bool EraseName(const string& strAddress)\r
     {\r
+        // This should only be used for sending addresses, never for receiving addresses,\r
+        // receiving addresses must always have an address book entry if they're not change return.\r
         CRITICAL_BLOCK(cs_mapAddressBook)\r
             mapAddressBook.erase(strAddress);\r
         nWalletDBUpdated++;\r
index db8886e..833a8a3 100644 (file)
--- a/init.cpp
+++ b/init.cpp
@@ -224,9 +224,6 @@ bool CMyApp::Initialize(int& argc, wxChar** argv)
         }\r
     }\r
 \r
-    if (fDaemon)\r
-        fprintf(stdout, "bitcoin server starting\n");\r
-\r
 #ifdef __WXGTK__\r
     if (fDaemon || fCommandLine)\r
     {\r
@@ -447,7 +444,8 @@ bool CMyApp::OnInit2()
     //\r
     // Load data files\r
     //\r
-    bool fFirstRun;\r
+    if (fDaemon)\r
+        fprintf(stdout, "bitcoin server starting\n");\r
     strErrors = "";\r
     int64 nStart;\r
 \r
@@ -465,6 +463,7 @@ bool CMyApp::OnInit2()
 \r
     printf("Loading wallet...\n");\r
     nStart = GetTimeMillis();\r
+    bool fFirstRun;\r
     if (!LoadWallet(fFirstRun))\r
         strErrors += _("Error loading wallet.dat      \n");\r
     printf(" wallet      %15"PRI64d"ms\n", GetTimeMillis() - nStart);\r
index ad0208a..05a182c 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -1336,19 +1336,12 @@ bool CBlock::AcceptBlock()
     if (!AddToBlockIndex(nFile, nBlockPos))\r
         return error("AcceptBlock() : AddToBlockIndex failed");\r
 \r
-    // Don't relay old inventory during initial block download.\r
-    // Please keep this number updated to a few thousand below current block count.\r
-    if (hashBestChain == hash && nBestHeight > 55000)\r
-        RelayInventory(CInv(MSG_BLOCK, hash));\r
-\r
-    // // Add atoms to user reviews for coins created\r
-    // vector<unsigned char> vchPubKey;\r
-    // if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey))\r
-    // {\r
-    //     unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100;\r
-    //     vector<unsigned short> vAtoms(1, nAtom);\r
-    //     AddAtomsAndPropagate(Hash(vchPubKey.begin(), vchPubKey.end()), vAtoms, true);\r
-    // }\r
+    // Relay inventory, but don't relay old inventory during initial block download\r
+    if (hashBestChain == hash)\r
+        CRITICAL_BLOCK(cs_vNodes)\r
+            foreach(CNode* pnode, vNodes)\r
+                if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 55000))\r
+                    pnode->PushInventory(CInv(MSG_BLOCK, hash));\r
 \r
     return true;\r
 }\r
@@ -1721,6 +1714,7 @@ bool ProcessMessages(CNode* pfrom)
     //  (4) message start\r
     //  (12) command\r
     //  (4) size\r
+    //  (4) checksum\r
     //  (x) data\r
     //\r
 \r
@@ -1728,12 +1722,13 @@ bool ProcessMessages(CNode* pfrom)
     {\r
         // Scan for message start\r
         CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));\r
-        if (vRecv.end() - pstart < sizeof(CMessageHeader))\r
+        int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());\r
+        if (vRecv.end() - pstart < nHeaderSize)\r
         {\r
-            if (vRecv.size() > sizeof(CMessageHeader))\r
+            if (vRecv.size() > nHeaderSize)\r
             {\r
                 printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");\r
-                vRecv.erase(vRecv.begin(), vRecv.end() - sizeof(CMessageHeader));\r
+                vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);\r
             }\r
             break;\r
         }\r
@@ -1742,6 +1737,7 @@ bool ProcessMessages(CNode* pfrom)
         vRecv.erase(vRecv.begin(), pstart);\r
 \r
         // Read header\r
+        vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);\r
         CMessageHeader hdr;\r
         vRecv >> hdr;\r
         if (!hdr.IsValid())\r
@@ -1757,10 +1753,9 @@ bool ProcessMessages(CNode* pfrom)
         {\r
             // Rewind and wait for rest of message\r
             ///// need a mechanism to give up waiting for overlong message size error\r
-            //if (fDebug)\r
-            //    printf("message-break\n");\r
-            vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));\r
-            Sleep(100);\r
+            if (fDebug)\r
+                printf("message-break\n");\r
+            vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());\r
             break;\r
         }\r
 \r
@@ -1768,6 +1763,20 @@ bool ProcessMessages(CNode* pfrom)
         CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);\r
         vRecv.ignore(nMessageSize);\r
 \r
+        // Checksum\r
+        if (vRecv.GetVersion() >= 209)\r
+        {\r
+            uint256 hash = Hash(vMsg.begin(), vMsg.end());\r
+            unsigned int nChecksum = 0;\r
+            memcpy(&nChecksum, &hash, sizeof(nChecksum));\r
+            if (nChecksum != hdr.nChecksum)\r
+            {\r
+                printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",\r
+                       strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);\r
+                continue;\r
+            }\r
+        }\r
+\r
         // Process message\r
         bool fRet = false;\r
         try\r
@@ -1844,6 +1853,9 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             vRecv >> addrFrom >> nNonce;\r
         if (pfrom->nVersion >= 106 && !vRecv.empty())\r
             vRecv >> strSubVer;\r
+        if (pfrom->nVersion >= 209 && !vRecv.empty())\r
+            vRecv >> pfrom->nStartingHeight;\r
+\r
         if (pfrom->nVersion == 0)\r
             return false;\r
 \r
@@ -1854,9 +1866,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             return true;\r
         }\r
 \r
-        pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));\r
-        pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));\r
-\r
         pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);\r
         if (pfrom->fClient)\r
         {\r
@@ -1866,6 +1875,13 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 \r
         AddTimeData(pfrom->addr.ip, nTime);\r
 \r
+        // Change version\r
+        if (pfrom->nVersion >= 209)\r
+            pfrom->PushMessage("verack");\r
+        pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));\r
+        if (pfrom->nVersion < 209)\r
+            pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));\r
+\r
         // Ask the first connected node for block updates\r
         static bool fAskedForBlocks;\r
         if (!fAskedForBlocks && !pfrom->fClient)\r
@@ -1876,7 +1892,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 \r
         pfrom->fSuccessfullyConnected = true;\r
 \r
-        printf("version message: version %d\n", pfrom->nVersion);\r
+        printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);\r
     }\r
 \r
 \r
@@ -1887,6 +1903,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     }\r
 \r
 \r
+    else if (strCommand == "verack")\r
+    {\r
+        pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));\r
+    }\r
+\r
+\r
     else if (strCommand == "addr")\r
     {\r
         vector<CAddress> vAddr;\r
@@ -2101,9 +2123,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         vRecv >> *pblock;\r
 \r
         //// debug print\r
-        // printf("received block:\n");\r
-        // pblock->print();\r
         printf("received block %s\n", pblock->GetHash().ToString().substr(0,16).c_str());\r
+        // pblock->print();\r
 \r
         CInv inv(MSG_BLOCK, pblock->GetHash());\r
         pfrom->AddInventoryKnown(inv);\r
@@ -2388,8 +2409,11 @@ void GenerateBitcoins(bool fGenerate)
         int nAddThreads = nProcessors - vnThreadsRunning[3];\r
         printf("Starting %d BitcoinMiner threads\n", nAddThreads);\r
         for (int i = 0; i < nAddThreads; i++)\r
+        {\r
             if (!CreateThread(ThreadBitcoinMiner, NULL))\r
                 printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");\r
+            Sleep(10);\r
+        }\r
     }\r
 }\r
 \r
index 449a960..ee63d11 100644 (file)
@@ -29,7 +29,7 @@ LIBS= \
 \r
 WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH\r
 DEBUGFLAGS=-g -D__WXDEBUG__\r
-CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)\r
+CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)\r
 HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \\r
     script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h\r
 \r
index 10c4eec..e7729ad 100644 (file)
@@ -29,7 +29,7 @@ LIBS= \
 \r
 WXDEFS=-D__WXGTK__ -DNOPCH\r
 DEBUGFLAGS=-g -D__WXDEBUG__\r
-CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)\r
+CFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)\r
 HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \\r
     script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h\r
 \r
diff --git a/net.h b/net.h
index 1593a97..46344ed 100644 (file)
--- a/net.h
+++ b/net.h
@@ -8,6 +8,7 @@ class CInv;
 class CRequestTracker;\r
 class CNode;\r
 class CBlockIndex;\r
+extern int nBestHeight;\r
 \r
 \r
 \r
@@ -59,7 +60,7 @@ public:
     char pchMessageStart[sizeof(::pchMessageStart)];\r
     char pchCommand[COMMAND_SIZE];\r
     unsigned int nMessageSize;\r
-    //unsigned int nChecksum;\r
+    unsigned int nChecksum;\r
 \r
     CMessageHeader()\r
     {\r
@@ -67,7 +68,7 @@ public:
         memset(pchCommand, 0, sizeof(pchCommand));\r
         pchCommand[1] = 1;\r
         nMessageSize = -1;\r
-        //nChecksum = 0;\r
+        nChecksum = 0;\r
     }\r
 \r
     CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)\r
@@ -75,6 +76,7 @@ public:
         memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));\r
         strncpy(pchCommand, pszCommand, COMMAND_SIZE);\r
         nMessageSize = nMessageSizeIn;\r
+        nChecksum = 0;\r
     }\r
 \r
     IMPLEMENT_SERIALIZE\r
@@ -82,8 +84,8 @@ public:
         READWRITE(FLATDATA(pchMessageStart));\r
         READWRITE(FLATDATA(pchCommand));\r
         READWRITE(nMessageSize);\r
-        //if (nVersion >= 209 && GetCommand() != "version")\r
-        //    READWRITE(nChecksum);\r
+        if (nVersion >= 209)\r
+            READWRITE(nChecksum);\r
     )\r
 \r
     string GetCommand()\r
@@ -475,6 +477,7 @@ extern CAddress addrProxy;
 \r
 \r
 \r
+\r
 class CNode\r
 {\r
 public:\r
@@ -507,6 +510,7 @@ public:
     uint256 hashContinue;\r
     CBlockIndex* pindexLastGetBlocksBegin;\r
     uint256 hashLastGetBlocksEnd;\r
+    int nStartingHeight;\r
 \r
     // flood\r
     vector<CAddress> vAddrToSend;\r
@@ -529,7 +533,9 @@ public:
         nServices = 0;\r
         hSocket = hSocketIn;\r
         vSend.SetType(SER_NETWORK);\r
+        vSend.SetVersion(0);\r
         vRecv.SetType(SER_NETWORK);\r
+        vRecv.SetVersion(0);\r
         nLastSend = 0;\r
         nLastRecv = 0;\r
         nLastSendEmpty = GetTime();\r
@@ -548,6 +554,7 @@ public:
         hashContinue = 0;\r
         pindexLastGetBlocksBegin = 0;\r
         hashLastGetBlocksEnd = 0;\r
+        nStartingHeight = -1;\r
         fGetAddr = false;\r
         nNextSendTxInv = 0;\r
         vfSubscribe.assign(256, false);\r
@@ -558,7 +565,8 @@ public:
         CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);\r
         CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost);\r
         RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));\r
-        PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, string(pszSubVer));\r
+        PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,\r
+                    nLocalHostNonce, string(pszSubVer), nBestHeight);\r
     }\r
 \r
     ~CNode()\r
@@ -680,10 +688,20 @@ public:
         if (nHeaderStart == -1)\r
             return;\r
 \r
-        // Patch in the size\r
+        // Set the size\r
         unsigned int nSize = vSend.size() - nMessageStart;\r
         memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));\r
 \r
+        // Set the checksum\r
+        if (vSend.GetVersion() >= 209)\r
+        {\r
+            uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());\r
+            unsigned int nChecksum = 0;\r
+            memcpy(&nChecksum, &hash, sizeof(nChecksum));\r
+            assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));\r
+            memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));\r
+        }\r
+\r
         printf("(%d bytes) ", nSize);\r
         printf("\n");\r
 \r
diff --git a/rpc.cpp b/rpc.cpp
index c56ce26..d988786 100644 (file)
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -26,7 +26,7 @@ void ThreadRPCServer2(void* parg);
 \r
 \r
 ///\r
-/// Note: I'm not finished designing this interface, it's still subject to change.\r
+/// Note: This interface may still be subject to change.\r
 ///\r
 \r
 \r
@@ -188,6 +188,73 @@ Value getnewaddress(const Array& params)
 }\r
 \r
 \r
+Value setlabel(const Array& params)\r
+{\r
+    if (params.size() < 1 || params.size() > 2)\r
+        throw runtime_error(\r
+            "setlabel <bitcoinaddress> <label>\n"\r
+            "Sets the label associated with the given address.");\r
+\r
+    string strAddress = params[0].get_str();\r
+    string strLabel;\r
+    if (params.size() > 1)\r
+        strLabel = params[1].get_str();\r
+\r
+    SetAddressBookName(strAddress, strLabel);\r
+    return Value::null;\r
+}\r
+\r
+\r
+Value getlabel(const Array& params)\r
+{\r
+    if (params.size() != 1)\r
+        throw runtime_error(\r
+            "getlabel <bitcoinaddress>\n"\r
+            "Returns the label associated with the given address.");\r
+\r
+    string strAddress = params[0].get_str();\r
+\r
+    string strLabel;\r
+    CRITICAL_BLOCK(cs_mapAddressBook)\r
+    {\r
+        map<string, string>::iterator mi = mapAddressBook.find(strAddress);\r
+        if (mi != mapAddressBook.end() && !(*mi).second.empty())\r
+            strLabel = (*mi).second;\r
+    }\r
+    return strLabel;\r
+}\r
+\r
+\r
+Value getaddressesbylabel(const Array& params)\r
+{\r
+    if (params.size() != 1)\r
+        throw runtime_error(\r
+            "getaddressesbylabel <label>\n"\r
+            "Returns the list of addresses with the given label.");\r
+\r
+    string strLabel = params[0].get_str();\r
+\r
+    // Find all addresses that have the given label\r
+    Array ret;\r
+    CRITICAL_BLOCK(cs_mapAddressBook)\r
+    {\r
+        foreach(const PAIRTYPE(string, string)& item, mapAddressBook)\r
+        {\r
+            const string& strAddress = item.first;\r
+            const string& strName = item.second;\r
+            if (strName == strLabel)\r
+            {\r
+                // We're only adding valid bitcoin addresses and not ip addresses\r
+                CScript scriptPubKey;\r
+                if (scriptPubKey.SetBitcoinAddress(strAddress))\r
+                    ret.push_back(strAddress);\r
+            }\r
+        }\r
+    }\r
+    return ret;\r
+}\r
+\r
+\r
 Value sendtoaddress(const Array& params)\r
 {\r
     if (params.size() < 2 || params.size() > 4)\r
@@ -237,11 +304,11 @@ Value listtransactions(const Array& params)
 }\r
 \r
 \r
-Value getamountreceived(const Array& params)\r
+Value getreceivedbyaddress(const Array& params)\r
 {\r
     if (params.size() < 1 || params.size() > 2)\r
         throw runtime_error(\r
-            "getamountreceived <bitcoinaddress> [minconf=1]\n"\r
+            "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"\r
             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");\r
 \r
     // Bitcoin address\r
@@ -249,6 +316,8 @@ Value getamountreceived(const Array& params)
     CScript scriptPubKey;\r
     if (!scriptPubKey.SetBitcoinAddress(strAddress))\r
         throw runtime_error("Invalid bitcoin address");\r
+    if (!IsMine(scriptPubKey))\r
+        return (double)0.0;\r
 \r
     // Minimum confirmations\r
     int nMinDepth = 1;\r
@@ -276,6 +345,59 @@ Value getamountreceived(const Array& params)
 }\r
 \r
 \r
+Value getreceivedbylabel(const Array& params)\r
+{\r
+    if (params.size() < 1 || params.size() > 2)\r
+        throw runtime_error(\r
+            "getreceivedbylabel <label> [minconf=1]\n"\r
+            "Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.");\r
+\r
+    // Get the set of pub keys that have the label\r
+    string strLabel = params[0].get_str();\r
+    set<CScript> setPubKey;\r
+    CRITICAL_BLOCK(cs_mapAddressBook)\r
+    {\r
+        foreach(const PAIRTYPE(string, string)& item, mapAddressBook)\r
+        {\r
+            const string& strAddress = item.first;\r
+            const string& strName = item.second;\r
+            if (strName == strLabel)\r
+            {\r
+                // We're only counting our own valid bitcoin addresses and not ip addresses\r
+                CScript scriptPubKey;\r
+                if (scriptPubKey.SetBitcoinAddress(strAddress))\r
+                    if (IsMine(scriptPubKey))\r
+                        setPubKey.insert(scriptPubKey);\r
+            }\r
+        }\r
+    }\r
+\r
+    // Minimum confirmations\r
+    int nMinDepth = 1;\r
+    if (params.size() > 1)\r
+        nMinDepth = params[1].get_int();\r
+\r
+    // Tally\r
+    int64 nAmount = 0;\r
+    CRITICAL_BLOCK(cs_mapWallet)\r
+    {\r
+        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)\r
+        {\r
+            const CWalletTx& wtx = (*it).second;\r
+            if (wtx.IsCoinBase() || !wtx.IsFinal())\r
+                continue;\r
+\r
+            foreach(const CTxOut& txout, wtx.vout)\r
+                if (setPubKey.count(txout.scriptPubKey))\r
+                    if (wtx.GetDepthInMainChain() >= nMinDepth)\r
+                        nAmount += txout.nValue;\r
+        }\r
+    }\r
+\r
+    return (double)nAmount / (double)COIN;\r
+}\r
+\r
+\r
 struct tallyitem\r
 {\r
     int64 nAmount;\r
@@ -287,23 +409,18 @@ struct tallyitem
     }\r
 };\r
 \r
-Value getallreceived(const Array& params)\r
+Value ListReceived(const Array& params, bool fByLabels)\r
 {\r
-    if (params.size() > 1)\r
-        throw runtime_error(\r
-            "getallreceived [minconf=1]\n"\r
-            "[minconf] is the minimum number of confirmations before payments are included.\n"\r
-            "Returns an array of objects containing:\n"\r
-            "  \"address\" : receiving address\n"\r
-            "  \"amount\" : total amount received by the address\n"\r
-            "  \"confirmations\" : number of confirmations of the most recent transaction included\n"\r
-            "  \"label\" : the label of the receiving address");\r
-\r
     // Minimum confirmations\r
     int nMinDepth = 1;\r
     if (params.size() > 0)\r
         nMinDepth = params[0].get_int();\r
 \r
+    // Whether to include empty accounts\r
+    bool fIncludeEmpty = false;\r
+    if (params.size() > 1)\r
+        fIncludeEmpty = params[1].get_bool();\r
+\r
     // Tally\r
     map<uint160, tallyitem> mapTally;\r
     CRITICAL_BLOCK(cs_mapWallet)\r
@@ -318,18 +435,11 @@ Value getallreceived(const Array& params)
             if (nDepth < nMinDepth)\r
                 continue;\r
 \r
-            // Filter out debits and payments to self, which may have change return\r
-            // we don't want to count.\r
-            int64 nCredit = wtx.GetCredit(true);\r
-            int64 nDebit = wtx.GetDebit();\r
-            int64 nNet = nCredit - nDebit;\r
-            if (nNet <= 0)\r
-                continue;\r
-\r
             foreach(const CTxOut& txout, wtx.vout)\r
             {\r
+                // Only counting our own bitcoin addresses and not ip addresses\r
                 uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();\r
-                if (hash160 == 0 || !mapPubKeys.count(hash160))\r
+                if (hash160 == 0 || !mapPubKeys.count(hash160)) // IsMine\r
                     continue;\r
 \r
                 tallyitem& item = mapTally[hash160];\r
@@ -341,27 +451,100 @@ Value getallreceived(const Array& params)
 \r
     // Reply\r
     Array ret;\r
+    map<string, tallyitem> mapLabelTally;\r
     CRITICAL_BLOCK(cs_mapAddressBook)\r
     {\r
-        for (map<uint160, tallyitem>::iterator it = mapTally.begin(); it != mapTally.end(); ++it)\r
+        foreach(const PAIRTYPE(string, string)& item, mapAddressBook)\r
         {\r
-            string strAddress = Hash160ToAddress((*it).first);\r
-            string strLabel;\r
-            map<string, string>::iterator mi = mapAddressBook.find(strAddress);\r
-            if (mi != mapAddressBook.end())\r
-                strLabel = (*mi).second;\r
+            const string& strAddress = item.first;\r
+            const string& strLabel = item.second;\r
+            uint160 hash160;\r
+            if (!AddressToHash160(strAddress, hash160))\r
+                continue;\r
+            map<uint160, tallyitem>::iterator it = mapTally.find(hash160);\r
+            if (it == mapTally.end() && !fIncludeEmpty)\r
+                continue;\r
+\r
+            int64 nAmount = 0;\r
+            int nConf = INT_MAX;\r
+            if (it != mapTally.end())\r
+            {\r
+                nAmount = (*it).second.nAmount;\r
+                nConf = (*it).second.nConf;\r
+            }\r
+\r
+            if (fByLabels)\r
+            {\r
+                tallyitem& item = mapLabelTally[strLabel];\r
+                item.nAmount += nAmount;\r
+                item.nConf = min(item.nConf, nConf);\r
+            }\r
+            else\r
+            {\r
+                Object obj;\r
+                obj.push_back(Pair("address",       strAddress));\r
+                obj.push_back(Pair("label",         strLabel));\r
+                obj.push_back(Pair("amount",        (double)nAmount / (double)COIN));\r
+                obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));\r
+                ret.push_back(obj);\r
+            }\r
+        }\r
+    }\r
 \r
+    if (fByLabels)\r
+    {\r
+        for (map<string, tallyitem>::iterator it = mapLabelTally.begin(); it != mapLabelTally.end(); ++it)\r
+        {\r
+            int64 nAmount = (*it).second.nAmount;\r
+            int nConf = (*it).second.nConf;\r
             Object obj;\r
-            obj.push_back(Pair("address",       strAddress));\r
-            obj.push_back(Pair("amount",        (double)(*it).second.nAmount / (double)COIN));\r
-            obj.push_back(Pair("confirmations", (*it).second.nConf));\r
-            obj.push_back(Pair("label",         strLabel));\r
+            obj.push_back(Pair("label",         (*it).first));\r
+            obj.push_back(Pair("amount",        (double)nAmount / (double)COIN));\r
+            obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));\r
             ret.push_back(obj);\r
         }\r
     }\r
+\r
     return ret;\r
 }\r
 \r
+Value listreceivedbyaddress(const Array& params)\r
+{\r
+    if (params.size() > 2)\r
+        throw runtime_error(\r
+            "listreceivedbyaddress [minconf=1] [includeempty=false]\n"\r
+            "[minconf] is the minimum number of confirmations before payments are included.\n"\r
+            "[includeempty] whether to include addresses that haven't received any payments.\n"\r
+            "Returns an array of objects containing:\n"\r
+            "  \"address\" : receiving address\n"\r
+            "  \"label\" : the label of the receiving address\n"\r
+            "  \"amount\" : total amount received by the address\n"\r
+            "  \"confirmations\" : number of confirmations of the most recent transaction included");\r
+\r
+    return ListReceived(params, false);\r
+}\r
+\r
+Value listreceivedbylabel(const Array& params)\r
+{\r
+    if (params.size() > 2)\r
+        throw runtime_error(\r
+            "listreceivedbylabel [minconf=1] [includeempty=false]\n"\r
+            "[minconf] is the minimum number of confirmations before payments are included.\n"\r
+            "[includeempty] whether to include labels that haven't received any payments.\n"\r
+            "Returns an array of objects containing:\n"\r
+            "  \"label\" : the label of the receiving addresses\n"\r
+            "  \"amount\" : total amount received by addresses with this label\n"\r
+            "  \"confirmations\" : number of confirmations of the most recent transaction included");\r
+\r
+    return ListReceived(params, true);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
 \r
 \r
 \r
@@ -375,20 +558,27 @@ Value getallreceived(const Array& params)
 typedef Value(*rpcfn_type)(const Array& params);\r
 pair<string, rpcfn_type> pCallTable[] =\r
 {\r
-    make_pair("stop",               &stop),\r
-    make_pair("getblockcount",      &getblockcount),\r
-    make_pair("getblocknumber",     &getblocknumber),\r
-    make_pair("getconnectioncount", &getconnectioncount),\r
-    make_pair("getdifficulty",      &getdifficulty),\r
-    make_pair("getbalance",         &getbalance),\r
-    make_pair("getgenerate",        &getgenerate),\r
-    make_pair("setgenerate",        &setgenerate),\r
-    make_pair("getinfo",            &getinfo),\r
-    make_pair("getnewaddress",      &getnewaddress),\r
-    make_pair("sendtoaddress",      &sendtoaddress),\r
-    make_pair("listtransactions",   &listtransactions),\r
-    make_pair("getamountreceived",  &getamountreceived),\r
-    make_pair("getallreceived",     &getallreceived),\r
+    make_pair("stop",                  &stop),\r
+    make_pair("getblockcount",         &getblockcount),\r
+    make_pair("getblocknumber",        &getblocknumber),\r
+    make_pair("getconnectioncount",    &getconnectioncount),\r
+    make_pair("getdifficulty",         &getdifficulty),\r
+    make_pair("getbalance",            &getbalance),\r
+    make_pair("getgenerate",           &getgenerate),\r
+    make_pair("setgenerate",           &setgenerate),\r
+    make_pair("getinfo",               &getinfo),\r
+    make_pair("getnewaddress",         &getnewaddress),\r
+    make_pair("setlabel",              &setlabel),\r
+    make_pair("getlabel",              &getlabel),\r
+    make_pair("getaddressesbylabel",   &getaddressesbylabel),\r
+    make_pair("sendtoaddress",         &sendtoaddress),\r
+    make_pair("listtransactions",      &listtransactions),\r
+    make_pair("getamountreceived",     &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress\r
+    make_pair("getallreceived",        &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress\r
+    make_pair("getreceivedbyaddress",  &getreceivedbyaddress),\r
+    make_pair("getreceivedbylabel",    &getreceivedbylabel),\r
+    make_pair("listreceivedbyaddress", &listreceivedbyaddress),\r
+    make_pair("listreceivedbylabel",   &listreceivedbylabel),\r
 };\r
 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));\r
 \r
@@ -666,13 +856,20 @@ int CommandLineRPC(int argc, char *argv[])
         //\r
         // Special case other types\r
         //\r
-        if (strMethod == "setgenerate"       && n > 0) ConvertTo<bool>(params[0]);\r
-        if (strMethod == "setgenerate"       && n > 1) ConvertTo<boost::int64_t>(params[1]);\r
-        if (strMethod == "sendtoaddress"     && n > 1) ConvertTo<double>(params[1]);\r
-        if (strMethod == "listtransactions"  && n > 0) ConvertTo<boost::int64_t>(params[0]);\r
-        if (strMethod == "listtransactions"  && n > 1) ConvertTo<bool>(params[1]);\r
-        if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]);\r
-        if (strMethod == "getallreceived"    && n > 0) ConvertTo<boost::int64_t>(params[0]);\r
+        if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);\r
+        if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);\r
+        if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);\r
+        if (strMethod == "listtransactions"       && n > 0) ConvertTo<boost::int64_t>(params[0]);\r
+        if (strMethod == "listtransactions"       && n > 1) ConvertTo<bool>(params[1]);\r
+        if (strMethod == "getamountreceived"      && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated\r
+        if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);\r
+        if (strMethod == "getreceivedbylabel"     && n > 1) ConvertTo<boost::int64_t>(params[1]);\r
+        if (strMethod == "getallreceived"         && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated\r
+        if (strMethod == "getallreceived"         && n > 1) ConvertTo<bool>(params[1]);\r
+        if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);\r
+        if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);\r
+        if (strMethod == "listreceivedbylabel"    && n > 0) ConvertTo<boost::int64_t>(params[0]);\r
+        if (strMethod == "listreceivedbylabel"    && n > 1) ConvertTo<bool>(params[1]);\r
 \r
         // Execute\r
         Value result = CallRPC(strMethod, params);\r
index c47dddc..2292651 100644 (file)
@@ -19,7 +19,7 @@ class CScript;
 class CDataStream;\r
 class CAutoFile;\r
 \r
-static const int VERSION = 208;\r
+static const int VERSION = 209;\r
 static const char* pszSubVer = ".0";\r
 \r
 \r
@@ -809,6 +809,18 @@ public:
             vch.insert(it, first, last);\r
     }\r
 \r
+    void insert(iterator it, vector<char>::const_iterator first, vector<char>::const_iterator last)\r
+    {\r
+        if (it == vch.begin() + nReadPos && last - first <= nReadPos)\r
+        {\r
+            // special case for inserting at the front when there's room\r
+            nReadPos -= (last - first);\r
+            memcpy(&vch[nReadPos], &first[0], last - first);\r
+        }\r
+        else\r
+            vch.insert(it, first, last);\r
+    }\r
+\r
 #if !defined(_MSC_VER) || _MSC_VER >= 1300\r
     void insert(iterator it, const char* first, const char* last)\r
     {\r
diff --git a/ui.cpp b/ui.cpp
index 5c7311f..e86456a 100644 (file)
--- a/ui.cpp
+++ b/ui.cpp
@@ -193,6 +193,12 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* pa
     return (ThreadSafeMessageBox(strMessage, strCaption, wxYES_NO, parent) == wxYES);\r
 }\r
 \r
+void CalledSetStatusBar(const string& strText, int nField)\r
+{\r
+    if (pframeMain && pframeMain->m_statusBar)\r
+        pframeMain->m_statusBar->SetStatusText(strText, nField);\r
+}\r
+\r
 void SetDefaultReceivingAddress(const string& strAddress)\r
 {\r
     // Update main window address and database\r
@@ -268,7 +274,8 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     if (!strstr(DateTimeStr(1229413914).c_str(), "2008"))\r
         nDateWidth += 12;\r
 #ifdef __WXMAC__\r
-    nDateWidth += 2;\r
+    nDateWidth += 5;\r
+    dResize -= 0.01;\r
 #endif\r
     wxListCtrl* pplistCtrl[] = {m_listCtrlAll, m_listCtrlSentReceived, m_listCtrlSent, m_listCtrlReceived};\r
     foreach(wxListCtrl* p, pplistCtrl)\r
diff --git a/ui.h b/ui.h
index e944eb9..a59e432 100644 (file)
--- a/ui.h
+++ b/ui.h
@@ -30,6 +30,7 @@ string FormatTxStatus(const CWalletTx& wtx);
 void UIThreadCall(boost::function0<void>);\r
 int ThreadSafeMessageBox(const string& message, const string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);\r
 bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent);\r
+void CalledSetStatusBar(const string& strText, int nField);\r
 void MainFrameRepaint();\r
 void CreateMainWindow();\r
 \r
@@ -48,6 +49,14 @@ inline bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWin
     return true;\r
 }\r
 \r
+inline void CalledSetStatusBar(const string& strText, int nField)\r
+{\r
+}\r
+\r
+inline void UIThreadCall(boost::function0<void> fn)\r
+{\r
+}\r
+\r
 inline void MainFrameRepaint()\r
 {\r
 }\r
index e2f0a1c..331934b 100644 (file)
--- a/uibase.h
+++ b/uibase.h
@@ -77,7 +77,6 @@ class CMainFrameBase : public wxFrame
                wxMenu* m_menuFile;\r
                wxMenu* m_menuHelp;\r
                wxToolBar* m_toolBar;\r
-               wxStatusBar* m_statusBar;\r
                \r
                wxStaticText* m_staticText32;\r
                wxButton* m_buttonNew;\r
@@ -121,6 +120,7 @@ class CMainFrameBase : public wxFrame
        \r
        public:\r
                wxMenu* m_menuOptions;\r
+               wxStatusBar* m_statusBar;\r
                wxTextCtrl* m_textCtrlAddress;\r
                wxListCtrl* m_listCtrlAll;\r
                wxListCtrl* m_listCtrlSentReceived;\r
index 990af52..58146ae 100644 (file)
                 <property name="maximum_size"></property>\r
                 <property name="minimum_size"></property>\r
                 <property name="name">m_statusBar</property>\r
-                <property name="permission">protected</property>\r
+                <property name="permission">public</property>\r
                 <property name="pos"></property>\r
                 <property name="size"></property>\r
                 <property name="style">wxST_SIZEGRIP</property>\r
index 8f6bf38..49f86d2 100644 (file)
--- a/util.cpp
+++ b/util.cpp
@@ -250,11 +250,6 @@ string strprintf(const char* format, ...)
         if (p == NULL)\r
             throw std::bad_alloc();\r
     }\r
-#ifdef _MSC_VER\r
-    // msvc optimisation\r
-    if (p == buffer)\r
-        return string(p, p+ret);\r
-#endif\r
     string str(p, p+ret);\r
     if (p != buffer)\r
         delete p;\r