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
This commit is contained in:
parent
9c1e9f0b6a
commit
7a47324c78
13 changed files with 364 additions and 101 deletions
2
db.h
2
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++;
|
||||
|
|
7
init.cpp
7
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);
|
||||
|
|
76
main.cpp
76
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
30
net.h
30
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");
|
||||
|
||||
|
|
305
rpc.cpp
305
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);
|
||||
|
|
14
serialize.h
14
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)
|
||||
{
|
||||
|
|
9
ui.cpp
9
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)
|
||||
|
|
9
ui.h
9
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()
|
||||
{
|
||||
}
|
||||
|
|
2
uibase.h
2
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;
|
||||
|
|
|
@ -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>
|
||||
|
|
5
util.cpp
5
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;
|
||||
|
|
Loading…
Reference in a new issue