From 42605ce8bcc9bd01b86491c74fee14de77960868 Mon Sep 17 00:00:00 2001 From: s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> 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 fb4e9268c..0b778d5fe 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 db8886e11..833a8a3f0 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 ad0208a25..05a182c18 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<unsigned char> vchPubKey; - // if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey)) - // { - // unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100; - // vector<unsigned short> 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<char> 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<CAddress> 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 449a96072..ee63d11ea 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 10c4eece7..e7729adca 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 1593a975a..46344ed92 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<CAddress> 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 c56ce263f..d988786ef 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 <bitcoinaddress> <label>\n" + "Sets the label associated with the given address."); + + string strAddress = params[0].get_str(); + string strLabel; + if (params.size() > 1) + strLabel = params[1].get_str(); + + SetAddressBookName(strAddress, strLabel); + return Value::null; +} + + +Value getlabel(const Array& params) +{ + if (params.size() != 1) + throw runtime_error( + "getlabel <bitcoinaddress>\n" + "Returns the label associated with the given address."); + + string strAddress = params[0].get_str(); + + string strLabel; + CRITICAL_BLOCK(cs_mapAddressBook) + { + map<string, string>::iterator mi = mapAddressBook.find(strAddress); + if (mi != mapAddressBook.end() && !(*mi).second.empty()) + strLabel = (*mi).second; + } + return strLabel; +} + + +Value getaddressesbylabel(const Array& params) +{ + if (params.size() != 1) + throw runtime_error( + "getaddressesbylabel <label>\n" + "Returns the list of addresses with the given label."); + + string strLabel = params[0].get_str(); + + // Find all addresses that have the given label + Array ret; + CRITICAL_BLOCK(cs_mapAddressBook) + { + foreach(const PAIRTYPE(string, string)& item, mapAddressBook) + { + const string& strAddress = item.first; + const string& strName = item.second; + if (strName == strLabel) + { + // We're only adding valid bitcoin addresses and not ip addresses + CScript scriptPubKey; + if (scriptPubKey.SetBitcoinAddress(strAddress)) + ret.push_back(strAddress); + } + } + } + return ret; +} + + Value sendtoaddress(const Array& params) { if (params.size() < 2 || params.size() > 4) @@ -237,11 +304,11 @@ Value listtransactions(const Array& params) } -Value getamountreceived(const Array& params) +Value getreceivedbyaddress(const Array& params) { if (params.size() < 1 || params.size() > 2) throw runtime_error( - "getamountreceived <bitcoinaddress> [minconf=1]\n" + "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n" "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations."); // Bitcoin address @@ -249,6 +316,8 @@ Value getamountreceived(const Array& params) CScript scriptPubKey; if (!scriptPubKey.SetBitcoinAddress(strAddress)) throw runtime_error("Invalid bitcoin address"); + if (!IsMine(scriptPubKey)) + return (double)0.0; // Minimum confirmations int nMinDepth = 1; @@ -276,6 +345,59 @@ Value getamountreceived(const Array& params) } +Value getreceivedbylabel(const Array& params) +{ + if (params.size() < 1 || params.size() > 2) + throw runtime_error( + "getreceivedbylabel <label> [minconf=1]\n" + "Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations."); + + // Get the set of pub keys that have the label + string strLabel = params[0].get_str(); + set<CScript> setPubKey; + CRITICAL_BLOCK(cs_mapAddressBook) + { + foreach(const PAIRTYPE(string, string)& item, mapAddressBook) + { + const string& strAddress = item.first; + const string& strName = item.second; + if (strName == strLabel) + { + // We're only counting our own valid bitcoin addresses and not ip addresses + CScript scriptPubKey; + if (scriptPubKey.SetBitcoinAddress(strAddress)) + if (IsMine(scriptPubKey)) + setPubKey.insert(scriptPubKey); + } + } + } + + // Minimum confirmations + int nMinDepth = 1; + if (params.size() > 1) + nMinDepth = params[1].get_int(); + + // Tally + int64 nAmount = 0; + CRITICAL_BLOCK(cs_mapWallet) + { + for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (wtx.IsCoinBase() || !wtx.IsFinal()) + continue; + + foreach(const CTxOut& txout, wtx.vout) + if (setPubKey.count(txout.scriptPubKey)) + if (wtx.GetDepthInMainChain() >= nMinDepth) + nAmount += txout.nValue; + } + } + + return (double)nAmount / (double)COIN; +} + + struct tallyitem { int64 nAmount; @@ -287,23 +409,18 @@ struct tallyitem } }; -Value getallreceived(const Array& params) +Value ListReceived(const Array& params, bool fByLabels) { - if (params.size() > 1) - throw runtime_error( - "getallreceived [minconf=1]\n" - "[minconf] is the minimum number of confirmations before payments are included.\n" - "Returns an array of objects containing:\n" - " \"address\" : receiving address\n" - " \"amount\" : total amount received by the address\n" - " \"confirmations\" : number of confirmations of the most recent transaction included\n" - " \"label\" : the label of the receiving address"); - // Minimum confirmations int nMinDepth = 1; if (params.size() > 0) nMinDepth = params[0].get_int(); + // Whether to include empty accounts + bool fIncludeEmpty = false; + if (params.size() > 1) + fIncludeEmpty = params[1].get_bool(); + // Tally map<uint160, tallyitem> mapTally; CRITICAL_BLOCK(cs_mapWallet) @@ -318,18 +435,11 @@ Value getallreceived(const Array& params) if (nDepth < nMinDepth) continue; - // Filter out debits and payments to self, which may have change return - // we don't want to count. - int64 nCredit = wtx.GetCredit(true); - int64 nDebit = wtx.GetDebit(); - int64 nNet = nCredit - nDebit; - if (nNet <= 0) - continue; - foreach(const CTxOut& txout, wtx.vout) { + // Only counting our own bitcoin addresses and not ip addresses uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160(); - if (hash160 == 0 || !mapPubKeys.count(hash160)) + if (hash160 == 0 || !mapPubKeys.count(hash160)) // IsMine continue; tallyitem& item = mapTally[hash160]; @@ -341,27 +451,100 @@ Value getallreceived(const Array& params) // Reply Array ret; + map<string, tallyitem> mapLabelTally; CRITICAL_BLOCK(cs_mapAddressBook) { - for (map<uint160, tallyitem>::iterator it = mapTally.begin(); it != mapTally.end(); ++it) + foreach(const PAIRTYPE(string, string)& item, mapAddressBook) { - string strAddress = Hash160ToAddress((*it).first); - string strLabel; - map<string, string>::iterator mi = mapAddressBook.find(strAddress); - if (mi != mapAddressBook.end()) - strLabel = (*mi).second; + const string& strAddress = item.first; + const string& strLabel = item.second; + uint160 hash160; + if (!AddressToHash160(strAddress, hash160)) + continue; + map<uint160, tallyitem>::iterator it = mapTally.find(hash160); + if (it == mapTally.end() && !fIncludeEmpty) + continue; + int64 nAmount = 0; + int nConf = INT_MAX; + if (it != mapTally.end()) + { + nAmount = (*it).second.nAmount; + nConf = (*it).second.nConf; + } + + if (fByLabels) + { + tallyitem& item = mapLabelTally[strLabel]; + item.nAmount += nAmount; + item.nConf = min(item.nConf, nConf); + } + else + { + Object obj; + obj.push_back(Pair("address", strAddress)); + obj.push_back(Pair("label", strLabel)); + obj.push_back(Pair("amount", (double)nAmount / (double)COIN)); + obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); + ret.push_back(obj); + } + } + } + + if (fByLabels) + { + for (map<string, tallyitem>::iterator it = mapLabelTally.begin(); it != mapLabelTally.end(); ++it) + { + int64 nAmount = (*it).second.nAmount; + int nConf = (*it).second.nConf; Object obj; - obj.push_back(Pair("address", strAddress)); - obj.push_back(Pair("amount", (double)(*it).second.nAmount / (double)COIN)); - obj.push_back(Pair("confirmations", (*it).second.nConf)); - obj.push_back(Pair("label", strLabel)); + obj.push_back(Pair("label", (*it).first)); + obj.push_back(Pair("amount", (double)nAmount / (double)COIN)); + obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); ret.push_back(obj); } } + return ret; } +Value listreceivedbyaddress(const Array& params) +{ + if (params.size() > 2) + throw runtime_error( + "listreceivedbyaddress [minconf=1] [includeempty=false]\n" + "[minconf] is the minimum number of confirmations before payments are included.\n" + "[includeempty] whether to include addresses that haven't received any payments.\n" + "Returns an array of objects containing:\n" + " \"address\" : receiving address\n" + " \"label\" : the label of the receiving address\n" + " \"amount\" : total amount received by the address\n" + " \"confirmations\" : number of confirmations of the most recent transaction included"); + + return ListReceived(params, false); +} + +Value listreceivedbylabel(const Array& params) +{ + if (params.size() > 2) + throw runtime_error( + "listreceivedbylabel [minconf=1] [includeempty=false]\n" + "[minconf] is the minimum number of confirmations before payments are included.\n" + "[includeempty] whether to include labels that haven't received any payments.\n" + "Returns an array of objects containing:\n" + " \"label\" : the label of the receiving addresses\n" + " \"amount\" : total amount received by addresses with this label\n" + " \"confirmations\" : number of confirmations of the most recent transaction included"); + + return ListReceived(params, true); +} + + + + + + + @@ -375,20 +558,27 @@ Value getallreceived(const Array& params) typedef Value(*rpcfn_type)(const Array& params); pair<string, rpcfn_type> pCallTable[] = { - make_pair("stop", &stop), - make_pair("getblockcount", &getblockcount), - make_pair("getblocknumber", &getblocknumber), - make_pair("getconnectioncount", &getconnectioncount), - make_pair("getdifficulty", &getdifficulty), - make_pair("getbalance", &getbalance), - make_pair("getgenerate", &getgenerate), - make_pair("setgenerate", &setgenerate), - make_pair("getinfo", &getinfo), - make_pair("getnewaddress", &getnewaddress), - make_pair("sendtoaddress", &sendtoaddress), - make_pair("listtransactions", &listtransactions), - make_pair("getamountreceived", &getamountreceived), - make_pair("getallreceived", &getallreceived), + make_pair("stop", &stop), + make_pair("getblockcount", &getblockcount), + make_pair("getblocknumber", &getblocknumber), + make_pair("getconnectioncount", &getconnectioncount), + make_pair("getdifficulty", &getdifficulty), + make_pair("getbalance", &getbalance), + make_pair("getgenerate", &getgenerate), + make_pair("setgenerate", &setgenerate), + make_pair("getinfo", &getinfo), + make_pair("getnewaddress", &getnewaddress), + make_pair("setlabel", &setlabel), + make_pair("getlabel", &getlabel), + make_pair("getaddressesbylabel", &getaddressesbylabel), + make_pair("sendtoaddress", &sendtoaddress), + make_pair("listtransactions", &listtransactions), + make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress + make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress + make_pair("getreceivedbyaddress", &getreceivedbyaddress), + make_pair("getreceivedbylabel", &getreceivedbylabel), + make_pair("listreceivedbyaddress", &listreceivedbyaddress), + make_pair("listreceivedbylabel", &listreceivedbylabel), }; map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); @@ -666,13 +856,20 @@ int CommandLineRPC(int argc, char *argv[]) // // Special case other types // - if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]); - if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]); - if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]); - if (strMethod == "listtransactions" && n > 0) ConvertTo<boost::int64_t>(params[0]); - if (strMethod == "listtransactions" && n > 1) ConvertTo<bool>(params[1]); - if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); - if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]); + if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]); + if (strMethod == "listtransactions" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listtransactions" && n > 1) ConvertTo<bool>(params[1]); + if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated + if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated + if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]); + if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]); + if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); // Execute Value result = CallRPC(strMethod, params); diff --git a/serialize.h b/serialize.h index c47dddc87..2292651e8 100644 --- a/serialize.h +++ b/serialize.h @@ -19,7 +19,7 @@ class CScript; class CDataStream; class CAutoFile; -static const int VERSION = 208; +static const int VERSION = 209; static const char* pszSubVer = ".0"; @@ -809,6 +809,18 @@ public: vch.insert(it, first, last); } + void insert(iterator it, vector<char>::const_iterator first, vector<char>::const_iterator last) + { + if (it == vch.begin() + nReadPos && last - first <= nReadPos) + { + // special case for inserting at the front when there's room + nReadPos -= (last - first); + memcpy(&vch[nReadPos], &first[0], last - first); + } + else + vch.insert(it, first, last); + } + #if !defined(_MSC_VER) || _MSC_VER >= 1300 void insert(iterator it, const char* first, const char* last) { diff --git a/ui.cpp b/ui.cpp index 5c7311f99..e86456a02 100644 --- 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); } +void CalledSetStatusBar(const string& strText, int nField) +{ + if (pframeMain && pframeMain->m_statusBar) + pframeMain->m_statusBar->SetStatusText(strText, nField); +} + void SetDefaultReceivingAddress(const string& strAddress) { // Update main window address and database @@ -268,7 +274,8 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) if (!strstr(DateTimeStr(1229413914).c_str(), "2008")) nDateWidth += 12; #ifdef __WXMAC__ - nDateWidth += 2; + nDateWidth += 5; + dResize -= 0.01; #endif wxListCtrl* pplistCtrl[] = {m_listCtrlAll, m_listCtrlSentReceived, m_listCtrlSent, m_listCtrlReceived}; foreach(wxListCtrl* p, pplistCtrl) diff --git a/ui.h b/ui.h index e944eb933..a59e43262 100644 --- a/ui.h +++ b/ui.h @@ -30,6 +30,7 @@ string FormatTxStatus(const CWalletTx& wtx); void UIThreadCall(boost::function0<void>); int ThreadSafeMessageBox(const string& message, const string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1); bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent); +void CalledSetStatusBar(const string& strText, int nField); void MainFrameRepaint(); void CreateMainWindow(); @@ -48,6 +49,14 @@ inline bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWin return true; } +inline void CalledSetStatusBar(const string& strText, int nField) +{ +} + +inline void UIThreadCall(boost::function0<void> fn) +{ +} + inline void MainFrameRepaint() { } diff --git a/uibase.h b/uibase.h index e2f0a1c09..331934b82 100644 --- a/uibase.h +++ b/uibase.h @@ -77,7 +77,6 @@ class CMainFrameBase : public wxFrame wxMenu* m_menuFile; wxMenu* m_menuHelp; wxToolBar* m_toolBar; - wxStatusBar* m_statusBar; wxStaticText* m_staticText32; wxButton* m_buttonNew; @@ -121,6 +120,7 @@ class CMainFrameBase : public wxFrame public: wxMenu* m_menuOptions; + wxStatusBar* m_statusBar; wxTextCtrl* m_textCtrlAddress; wxListCtrl* m_listCtrlAll; wxListCtrl* m_listCtrlSentReceived; diff --git a/uiproject.fbp b/uiproject.fbp index 990af5219..58146ae5e 100644 --- a/uiproject.fbp +++ b/uiproject.fbp @@ -293,7 +293,7 @@ <property name="maximum_size"></property> <property name="minimum_size"></property> <property name="name">m_statusBar</property> - <property name="permission">protected</property> + <property name="permission">public</property> <property name="pos"></property> <property name="size"></property> <property name="style">wxST_SIZEGRIP</property> diff --git a/util.cpp b/util.cpp index 8f6bf38c4..49f86d2de 100644 --- a/util.cpp +++ b/util.cpp @@ -250,11 +250,6 @@ string strprintf(const char* format, ...) if (p == NULL) throw std::bad_alloc(); } -#ifdef _MSC_VER - // msvc optimisation - if (p == buffer) - return string(p, p+ret); -#endif string str(p, p+ret); if (p != buffer) delete p;