diff options
author | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-05-26 00:05:26 +0000 |
---|---|---|
committer | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-05-26 00:05:26 +0000 |
commit | 42605ce8bcc9bd01b86491c74fee14de77960868 (patch) | |
tree | 4b2b30223b78d51882769886945c63f5427a812b | |
parent | 124baa4ccbf3ecb78eab7ecdd40105fb54ee0369 (diff) |
better prevention of inventory relaying during initial download,v0.2.9
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
-rw-r--r-- | db.h | 2 | ||||
-rw-r--r-- | init.cpp | 7 | ||||
-rw-r--r-- | main.cpp | 76 | ||||
-rw-r--r-- | makefile.mingw | 2 | ||||
-rw-r--r-- | makefile.unix | 2 | ||||
-rw-r--r-- | net.h | 30 | ||||
-rw-r--r-- | rpc.cpp | 305 | ||||
-rw-r--r-- | serialize.h | 14 | ||||
-rw-r--r-- | ui.cpp | 9 | ||||
-rw-r--r-- | ui.h | 9 | ||||
-rw-r--r-- | uibase.h | 2 | ||||
-rw-r--r-- | uiproject.fbp | 2 | ||||
-rw-r--r-- | util.cpp | 5 |
13 files changed, 364 insertions, 101 deletions
@@ -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++;
@@ -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);
@@ -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 449a96072c..ee63d11ead 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 10c4eece73..e7729adcaa 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
@@ -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");
@@ -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 c47dddc87c..2292651e83 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)
{
@@ -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)
@@ -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()
{
}
@@ -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 990af52196..58146ae5eb 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>
@@ -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;
|