automatically change displayed address whenever it receives anything,

added help and -? for daemon command line rpc commands,
only relay addr messages to 5 random nodes to save bandwidth,
started setting wtx.fFromMe flag,
trickle out tx inventory messages to protect privacy
 -- version 0.2.10
This commit is contained in:
s_nakamoto 2010-06-10 23:10:30 +00:00
parent d9dac6772f
commit 3b318ed095
16 changed files with 265 additions and 140 deletions

9
db.cpp
View file

@ -511,9 +511,9 @@ bool LoadAddresses()
// CWalletDB // CWalletDB
// //
bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet) bool CWalletDB::LoadWallet()
{ {
vchDefaultKeyRet.clear(); vchDefaultKey.clear();
int nFileVersion = 0; int nFileVersion = 0;
// Modify defaults // Modify defaults
@ -587,7 +587,7 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
} }
else if (strType == "defaultkey") else if (strType == "defaultkey")
{ {
ssValue >> vchDefaultKeyRet; ssValue >> vchDefaultKey;
} }
else if (strType == "version") else if (strType == "version")
{ {
@ -650,8 +650,7 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
bool LoadWallet(bool& fFirstRunRet) bool LoadWallet(bool& fFirstRunRet)
{ {
fFirstRunRet = false; fFirstRunRet = false;
vector<unsigned char> vchDefaultKey; if (!CWalletDB("cr+").LoadWallet())
if (!CWalletDB("cr+").LoadWallet(vchDefaultKey))
return false; return false;
fFirstRunRet = vchDefaultKey.empty(); fFirstRunRet = vchDefaultKey.empty();

5
db.h
View file

@ -14,9 +14,11 @@ class CWalletTx;
extern map<string, string> mapAddressBook; extern map<string, string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook; extern CCriticalSection cs_mapAddressBook;
extern vector<unsigned char> vchDefaultKey;
extern bool fClient; extern bool fClient;
extern unsigned int nWalletDBUpdated; extern unsigned int nWalletDBUpdated;
extern DbEnv dbenv; extern DbEnv dbenv;
@ -373,6 +375,7 @@ public:
bool WriteDefaultKey(const vector<unsigned char>& vchPubKey) bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
{ {
vchDefaultKey = vchPubKey;
nWalletDBUpdated++; nWalletDBUpdated++;
return Write(string("defaultkey"), vchPubKey); return Write(string("defaultkey"), vchPubKey);
} }
@ -390,7 +393,7 @@ public:
return Write(make_pair(string("setting"), strKey), value); return Write(make_pair(string("setting"), strKey), value);
} }
bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet); bool LoadWallet();
}; };
bool LoadWallet(bool& fFirstRunRet); bool LoadWallet(bool& fFirstRunRet);

View file

@ -339,22 +339,27 @@ bool CMyApp::OnInit2()
if (mapArgs.count("-?") || mapArgs.count("--help")) if (mapArgs.count("-?") || mapArgs.count("--help"))
{ {
wxString strUsage = string() + wxString strUsage = string() +
_("Usage: bitcoin [options]") + "\t\t\t\t\t\t\n" + _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
" bitcoin [options] \t" + "\n" +
" bitcoin [command] \t" + _("Send command to bitcoin running with -server or -daemon\n") +
" bitcoin [command] -? \t" + _("Get help for a command\n") +
" bitcoin help \t" + _("List commands\n") +
_("Options:\n") + _("Options:\n") +
" -gen \t\t " + _("Generate coins\n") + " -gen \t " + _("Generate coins\n") +
" -gen=0 \t\t " + _("Don't generate coins\n") + " -gen=0 \t " + _("Don't generate coins\n") +
" -min \t\t " + _("Start minimized\n") + " -min \t " + _("Start minimized\n") +
" -datadir=<dir> \t " + _("Specify data directory\n") + " -datadir=<dir> \t " + _("Specify data directory\n") +
" -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") + " -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
" -addnode=<ip> \t " + _("Add a node to connect to\n") + " -addnode=<ip> \t " + _("Add a node to connect to\n") +
" -connect=<ip> \t " + _("Connect only to the specified node\n") + " -connect=<ip> \t " + _("Connect only to the specified node\n") +
" -? \t\t " + _("This help message\n"); " -server \t " + _("Accept command line and JSON-RPC commands\n") +
" -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
" -? \t " + _("This help message\n");
if (fWindows && fGUI) if (fWindows && fGUI)
{ {
// Remove spaces, the tabs make the columns line up in the message box // Tabs make the columns line up in the message box
for (int i = 0; i < 50; i++)
strUsage.Replace(" \t", "\t");
wxMessageBox(strUsage, "Bitcoin", wxOK); wxMessageBox(strUsage, "Bitcoin", wxOK);
} }
else else

View file

@ -159,7 +159,6 @@ bool Wait(int nSeconds)
void ThreadIRCSeed(void* parg) void ThreadIRCSeed(void* parg)
{ {
printf("ThreadIRCSeed started\n"); printf("ThreadIRCSeed started\n");
SetThreadPriority(THREAD_PRIORITY_NORMAL);
int nErrorWait = 10; int nErrorWait = 10;
int nRetryWait = 10; int nRetryWait = 10;
bool fNameInUse = false; bool fNameInUse = false;

View file

@ -49,6 +49,8 @@ CCriticalSection cs_mapRequestCount;
map<string, string> mapAddressBook; map<string, string> mapAddressBook;
CCriticalSection cs_mapAddressBook; CCriticalSection cs_mapAddressBook;
vector<unsigned char> vchDefaultKey;
// Settings // Settings
int fGenerateBitcoins = false; int fGenerateBitcoins = false;
int64 nTransactionFee = 0; int64 nTransactionFee = 0;
@ -142,6 +144,19 @@ bool AddToWallet(const CWalletTx& wtxIn)
if (!wtx.WriteToDisk()) if (!wtx.WriteToDisk())
return false; return false;
// If default receiving address gets used, replace it with a new one
CScript scriptDefaultKey;
scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
foreach(const CTxOut& txout, wtx.vout)
{
if (txout.scriptPubKey == scriptDefaultKey)
{
CWalletDB walletdb;
walletdb.WriteDefaultKey(GenerateNewKey());
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
}
}
// Notify UI // Notify UI
vWalletUpdated.push_back(hash); vWalletUpdated.push_back(hash);
} }
@ -1753,8 +1768,6 @@ bool ProcessMessages(CNode* pfrom)
{ {
// Rewind and wait for rest of message // Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error ///// need a mechanism to give up waiting for overlong message size error
if (fDebug)
printf("message-break\n");
vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end()); vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
break; break;
} }
@ -1922,18 +1935,25 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (fShutdown) if (fShutdown)
return true; return true;
addr.nTime = GetAdjustedTime() - 2 * 60 * 60; addr.nTime = GetAdjustedTime() - 2 * 60 * 60;
if (pfrom->fGetAddr) if (pfrom->fGetAddr || vAddr.size() > 10)
addr.nTime -= 5 * 24 * 60 * 60; addr.nTime -= 5 * 24 * 60 * 60;
AddAddress(addr, false); AddAddress(addr, false);
pfrom->AddAddressKnown(addr); pfrom->AddAddressKnown(addr);
if (!pfrom->fGetAddr && addr.IsRoutable()) if (!pfrom->fGetAddr && addr.IsRoutable())
{ {
// Put on lists to send to other nodes // Relay to a limited number of other nodes
CRITICAL_BLOCK(cs_vNodes) CRITICAL_BLOCK(cs_vNodes)
{
multimap<int, CNode*> mapMix;
foreach(CNode* pnode, vNodes) foreach(CNode* pnode, vNodes)
pnode->PushAddress(addr); mapMix.insert(make_pair(GetRand(INT_MAX), pnode));
int nRelayNodes = 5;
for (multimap<int, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
((*mi).second)->PushAddress(addr);
} }
} }
}
if (vAddr.size() < 1000)
pfrom->fGetAddr = false; pfrom->fGetAddr = false;
} }
@ -2177,6 +2197,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
uint256 hashReply; uint256 hashReply;
CWalletTx wtxNew; CWalletTx wtxNew;
vRecv >> hashReply >> wtxNew; vRecv >> hashReply >> wtxNew;
wtxNew.fFromMe = false;
// Broadcast // Broadcast
if (!wtxNew.AcceptWalletTransaction()) if (!wtxNew.AcceptWalletTransaction())
@ -2242,7 +2263,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
bool SendMessages(CNode* pto) bool SendMessages(CNode* pto, bool fSendTrickle)
{ {
CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_main)
{ {
@ -2273,15 +2294,6 @@ bool SendMessages(CNode* pto)
} }
} }
// Delay tx inv messages to protect privacy,
// trickle them out to a few nodes at a time.
bool fSendTxInv = false;
if (GetTimeMillis() > pto->nNextSendTxInv)
{
pto->nNextSendTxInv = GetTimeMillis() + 3000 + GetRand(2000);
fSendTxInv = true;
}
// Resend wallet transactions that haven't gotten in a block yet // Resend wallet transactions that haven't gotten in a block yet
ResendWalletTransactions(); ResendWalletTransactions();
@ -2289,6 +2301,8 @@ bool SendMessages(CNode* pto)
// //
// Message: addr // Message: addr
// //
if (fSendTrickle)
{
vector<CAddress> vAddr; vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size()); vAddr.reserve(pto->vAddrToSend.size());
foreach(const CAddress& addr, pto->vAddrToSend) foreach(const CAddress& addr, pto->vAddrToSend)
@ -2307,6 +2321,7 @@ bool SendMessages(CNode* pto)
pto->vAddrToSend.clear(); pto->vAddrToSend.clear();
if (!vAddr.empty()) if (!vAddr.empty())
pto->PushMessage("addr", vAddr); pto->PushMessage("addr", vAddr);
}
// //
@ -2320,12 +2335,41 @@ bool SendMessages(CNode* pto)
vInvWait.reserve(pto->vInventoryToSend.size()); vInvWait.reserve(pto->vInventoryToSend.size());
foreach(const CInv& inv, pto->vInventoryToSend) foreach(const CInv& inv, pto->vInventoryToSend)
{ {
// delay txes if (pto->setInventoryKnown.count(inv))
if (!fSendTxInv && inv.type == MSG_TX) continue;
// trickle out tx inv to protect privacy
if (inv.type == MSG_TX && !fSendTrickle)
{
// 1/4 of tx invs blast to all immediately
static uint256 hashSalt;
if (hashSalt == 0)
RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
uint256 hashRand = (inv.hash ^ hashSalt);
hashRand = Hash(BEGIN(hashRand), END(hashRand));
bool fTrickleWait = ((hashRand & 3) != 0);
// always trickle our own transactions
if (!fTrickleWait)
{
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(inv.hash);
if (mi != mapWallet.end())
{
CWalletTx& wtx = (*mi).second;
if (wtx.fFromMe)
fTrickleWait = true;
}
}
}
if (fTrickleWait)
{ {
vInvWait.push_back(inv); vInvWait.push_back(inv);
continue; continue;
} }
}
// returns true if wasn't already contained in the set // returns true if wasn't already contained in the set
if (pto->setInventoryKnown.insert(inv).second) if (pto->setInventoryKnown.insert(inv).second)
@ -2852,6 +2896,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
{ {
wtxNew.vin.clear(); wtxNew.vin.clear();
wtxNew.vout.clear(); wtxNew.vout.clear();
wtxNew.fFromMe = true;
if (nValue < 0) if (nValue < 0)
return false; return false;
int64 nValueOut = nValue; int64 nValueOut = nValue;

3
main.h
View file

@ -38,6 +38,7 @@ extern map<uint256, int> mapRequestCount;
extern CCriticalSection cs_mapRequestCount; extern CCriticalSection cs_mapRequestCount;
extern map<string, string> mapAddressBook; extern map<string, string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook; extern CCriticalSection cs_mapAddressBook;
extern vector<unsigned char> vchDefaultKey;
// Settings // Settings
extern int fGenerateBitcoins; extern int fGenerateBitcoins;
@ -66,7 +67,7 @@ bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree(); void PrintBlockTree();
bool ProcessMessages(CNode* pfrom); bool ProcessMessages(CNode* pfrom);
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv); bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
bool SendMessages(CNode* pto); bool SendMessages(CNode* pto, bool fSendTrickle);
int64 GetBalance(); int64 GetBalance();
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet); bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key); bool CommitTransaction(CWalletTx& wtxNew, const CKey& key);

View file

@ -1019,7 +1019,6 @@ void ThreadMessageHandler2(void* parg)
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
while (!fShutdown) while (!fShutdown)
{ {
// Poll the connected nodes for messages
vector<CNode*> vNodesCopy; vector<CNode*> vNodesCopy;
CRITICAL_BLOCK(cs_vNodes) CRITICAL_BLOCK(cs_vNodes)
{ {
@ -1027,6 +1026,11 @@ void ThreadMessageHandler2(void* parg)
foreach(CNode* pnode, vNodesCopy) foreach(CNode* pnode, vNodesCopy)
pnode->AddRef(); pnode->AddRef();
} }
// Poll the connected nodes for messages
CNode* pnodeTrickle = NULL;
if (!vNodesCopy.empty())
pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
foreach(CNode* pnode, vNodesCopy) foreach(CNode* pnode, vNodesCopy)
{ {
// Receive messages // Receive messages
@ -1037,10 +1041,11 @@ void ThreadMessageHandler2(void* parg)
// Send messages // Send messages
TRY_CRITICAL_BLOCK(pnode->cs_vSend) TRY_CRITICAL_BLOCK(pnode->cs_vSend)
SendMessages(pnode); SendMessages(pnode, pnode == pnodeTrickle);
if (fShutdown) if (fShutdown)
return; return;
} }
CRITICAL_BLOCK(cs_vNodes) CRITICAL_BLOCK(cs_vNodes)
{ {
foreach(CNode* pnode, vNodesCopy) foreach(CNode* pnode, vNodesCopy)

10
net.h
View file

@ -12,7 +12,7 @@ extern int nBestHeight;
static const unsigned short DEFAULT_PORT = htons(8333); #define DEFAULT_PORT htons(8333)
static const unsigned int PUBLISH_HOPS = 5; static const unsigned int PUBLISH_HOPS = 5;
enum enum
{ {
@ -522,7 +522,6 @@ public:
vector<CInv> vInventoryToSend; vector<CInv> vInventoryToSend;
CCriticalSection cs_inventory; CCriticalSection cs_inventory;
multimap<int64, CInv> mapAskFor; multimap<int64, CInv> mapAskFor;
int64 nNextSendTxInv;
// publish and subscription // publish and subscription
vector<char> vfSubscribe; vector<char> vfSubscribe;
@ -536,6 +535,12 @@ public:
vSend.SetVersion(0); vSend.SetVersion(0);
vRecv.SetType(SER_NETWORK); vRecv.SetType(SER_NETWORK);
vRecv.SetVersion(0); vRecv.SetVersion(0);
// Version 0.2 obsoletes 20 Feb 2012
if (GetTime() > 1329696000)
{
vSend.SetVersion(209);
vRecv.SetVersion(209);
}
nLastSend = 0; nLastSend = 0;
nLastRecv = 0; nLastRecv = 0;
nLastSendEmpty = GetTime(); nLastSendEmpty = GetTime();
@ -556,7 +561,6 @@ public:
hashLastGetBlocksEnd = 0; hashLastGetBlocksEnd = 0;
nStartingHeight = -1; nStartingHeight = -1;
fGetAddr = false; fGetAddr = false;
nNextSendTxInv = 0;
vfSubscribe.assign(256, false); vfSubscribe.assign(256, false);
// Push a version message // Push a version message

149
rpc.cpp
View file

@ -18,6 +18,8 @@ using boost::asio::ip::tcp;
using namespace json_spirit; using namespace json_spirit;
void ThreadRPCServer2(void* parg); void ThreadRPCServer2(void* parg);
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
extern map<string, rpcfn_type> mapCallTable;
@ -31,11 +33,40 @@ void ThreadRPCServer2(void* parg);
Value stop(const Array& params) Value help(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"stop (no parameters)\n" "help\n"
"List commands.");
string strRet;
for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
{
try
{
Array params;
(*(*mi).second)(params, true);
}
catch (std::exception& e)
{
// Help text is returned in an exception
string strHelp = string(e.what());
if (strHelp.find('\n') != -1)
strHelp = strHelp.substr(0, strHelp.find('\n'));
strRet += strHelp + "\n";
}
}
strRet = strRet.substr(0,strRet.size()-1);
return strRet;
}
Value stop(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"stop\n"
"Stop bitcoin server."); "Stop bitcoin server.");
// Shutdown will take long enough that the response should get back // Shutdown will take long enough that the response should get back
@ -44,33 +75,33 @@ Value stop(const Array& params)
} }
Value getblockcount(const Array& params) Value getblockcount(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getblockcount (no parameters)\n" "getblockcount\n"
"Returns the number of blocks in the longest block chain."); "Returns the number of blocks in the longest block chain.");
return nBestHeight + 1; return nBestHeight + 1;
} }
Value getblocknumber(const Array& params) Value getblocknumber(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getblocknumber (no parameters)\n" "getblocknumber\n"
"Returns the block number of the latest block in the longest block chain."); "Returns the block number of the latest block in the longest block chain.");
return nBestHeight; return nBestHeight;
} }
Value getconnectioncount(const Array& params) Value getconnectioncount(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getconnectioncount (no parameters)\n" "getconnectioncount\n"
"Returns the number of connections to other nodes."); "Returns the number of connections to other nodes.");
return (int)vNodes.size(); return (int)vNodes.size();
@ -89,42 +120,42 @@ double GetDifficulty()
return dMinimum / dCurrently; return dMinimum / dCurrently;
} }
Value getdifficulty(const Array& params) Value getdifficulty(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getdifficulty (no parameters)\n" "getdifficulty\n"
"Returns the proof-of-work difficulty as a multiple of the minimum difficulty."); "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
return GetDifficulty(); return GetDifficulty();
} }
Value getbalance(const Array& params) Value getbalance(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getbalance (no parameters)\n" "getbalance\n"
"Returns the server's available balance."); "Returns the server's available balance.");
return ((double)GetBalance() / (double)COIN); return ((double)GetBalance() / (double)COIN);
} }
Value getgenerate(const Array& params) Value getgenerate(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getgenerate (no parameters)\n" "getgenerate\n"
"Returns true or false."); "Returns true or false.");
return (bool)fGenerateBitcoins; return (bool)fGenerateBitcoins;
} }
Value setgenerate(const Array& params) Value setgenerate(const Array& params, bool fHelp)
{ {
if (params.size() < 1 || params.size() > 2) if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error( throw runtime_error(
"setgenerate <generate> [genproclimit]\n" "setgenerate <generate> [genproclimit]\n"
"<generate> is true or false to turn generation on or off.\n" "<generate> is true or false to turn generation on or off.\n"
@ -148,11 +179,11 @@ Value setgenerate(const Array& params)
} }
Value getinfo(const Array& params) Value getinfo(const Array& params, bool fHelp)
{ {
if (params.size() != 0) if (fHelp || params.size() != 0)
throw runtime_error( throw runtime_error(
"getinfo (no parameters)"); "getinfo");
Object obj; Object obj;
obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN)); obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN));
@ -166,9 +197,9 @@ Value getinfo(const Array& params)
} }
Value getnewaddress(const Array& params) Value getnewaddress(const Array& params, bool fHelp)
{ {
if (params.size() > 1) if (fHelp || params.size() > 1)
throw runtime_error( throw runtime_error(
"getnewaddress [label]\n" "getnewaddress [label]\n"
"Returns a new bitcoin address for receiving payments. " "Returns a new bitcoin address for receiving payments. "
@ -188,9 +219,9 @@ Value getnewaddress(const Array& params)
} }
Value setlabel(const Array& params) Value setlabel(const Array& params, bool fHelp)
{ {
if (params.size() < 1 || params.size() > 2) if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error( throw runtime_error(
"setlabel <bitcoinaddress> <label>\n" "setlabel <bitcoinaddress> <label>\n"
"Sets the label associated with the given address."); "Sets the label associated with the given address.");
@ -205,9 +236,9 @@ Value setlabel(const Array& params)
} }
Value getlabel(const Array& params) Value getlabel(const Array& params, bool fHelp)
{ {
if (params.size() != 1) if (fHelp || params.size() != 1)
throw runtime_error( throw runtime_error(
"getlabel <bitcoinaddress>\n" "getlabel <bitcoinaddress>\n"
"Returns the label associated with the given address."); "Returns the label associated with the given address.");
@ -225,9 +256,9 @@ Value getlabel(const Array& params)
} }
Value getaddressesbylabel(const Array& params) Value getaddressesbylabel(const Array& params, bool fHelp)
{ {
if (params.size() != 1) if (fHelp || params.size() != 1)
throw runtime_error( throw runtime_error(
"getaddressesbylabel <label>\n" "getaddressesbylabel <label>\n"
"Returns the list of addresses with the given label."); "Returns the list of addresses with the given label.");
@ -255,9 +286,9 @@ Value getaddressesbylabel(const Array& params)
} }
Value sendtoaddress(const Array& params) Value sendtoaddress(const Array& params, bool fHelp)
{ {
if (params.size() < 2 || params.size() > 4) if (fHelp || params.size() < 2 || params.size() > 4)
throw runtime_error( throw runtime_error(
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n" "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
"<amount> is a real and is rounded to the nearest 0.01"); "<amount> is a real and is rounded to the nearest 0.01");
@ -283,9 +314,9 @@ Value sendtoaddress(const Array& params)
} }
Value listtransactions(const Array& params) Value listtransactions(const Array& params, bool fHelp)
{ {
if (params.size() > 2) if (fHelp || params.size() > 2)
throw runtime_error( throw runtime_error(
"listtransactions [count=10] [includegenerated=false]\n" "listtransactions [count=10] [includegenerated=false]\n"
"Returns up to [count] most recent transactions."); "Returns up to [count] most recent transactions.");
@ -304,9 +335,9 @@ Value listtransactions(const Array& params)
} }
Value getreceivedbyaddress(const Array& params) Value getreceivedbyaddress(const Array& params, bool fHelp)
{ {
if (params.size() < 1 || params.size() > 2) if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error( throw runtime_error(
"getreceivedbyaddress <bitcoinaddress> [minconf=1]\n" "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
"Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations."); "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
@ -345,9 +376,9 @@ Value getreceivedbyaddress(const Array& params)
} }
Value getreceivedbylabel(const Array& params) Value getreceivedbylabel(const Array& params, bool fHelp)
{ {
if (params.size() < 1 || params.size() > 2) if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error( throw runtime_error(
"getreceivedbylabel <label> [minconf=1]\n" "getreceivedbylabel <label> [minconf=1]\n"
"Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations."); "Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.");
@ -508,9 +539,9 @@ Value ListReceived(const Array& params, bool fByLabels)
return ret; return ret;
} }
Value listreceivedbyaddress(const Array& params) Value listreceivedbyaddress(const Array& params, bool fHelp)
{ {
if (params.size() > 2) if (fHelp || params.size() > 2)
throw runtime_error( throw runtime_error(
"listreceivedbyaddress [minconf=1] [includeempty=false]\n" "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n" "[minconf] is the minimum number of confirmations before payments are included.\n"
@ -524,9 +555,9 @@ Value listreceivedbyaddress(const Array& params)
return ListReceived(params, false); return ListReceived(params, false);
} }
Value listreceivedbylabel(const Array& params) Value listreceivedbylabel(const Array& params, bool fHelp)
{ {
if (params.size() > 2) if (fHelp || params.size() > 2)
throw runtime_error( throw runtime_error(
"listreceivedbylabel [minconf=1] [includeempty=false]\n" "listreceivedbylabel [minconf=1] [includeempty=false]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n" "[minconf] is the minimum number of confirmations before payments are included.\n"
@ -555,9 +586,9 @@ Value listreceivedbylabel(const Array& params)
// Call Table // Call Table
// //
typedef Value(*rpcfn_type)(const Array& params);
pair<string, rpcfn_type> pCallTable[] = pair<string, rpcfn_type> pCallTable[] =
{ {
make_pair("help", &help),
make_pair("stop", &stop), make_pair("stop", &stop),
make_pair("getblockcount", &getblockcount), make_pair("getblockcount", &getblockcount),
make_pair("getblocknumber", &getblocknumber), make_pair("getblocknumber", &getblocknumber),
@ -760,7 +791,7 @@ void ThreadRPCServer2(void* parg)
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod); map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
if (mi == mapCallTable.end()) if (mi == mapCallTable.end())
throw runtime_error("Method not found."); throw runtime_error("Method not found.");
Value result = (*(*mi).second)(params); Value result = (*(*mi).second)(params, false);
// Send reply // Send reply
string strReply = JSONRPCReply(result, Value::null, id); string strReply = JSONRPCReply(result, Value::null, id);
@ -847,6 +878,23 @@ int CommandLineRPC(int argc, char *argv[])
if (!mapCallTable.count(strMethod)) if (!mapCallTable.count(strMethod))
throw runtime_error(strprintf("unknown command: %s", strMethod.c_str())); throw runtime_error(strprintf("unknown command: %s", strMethod.c_str()));
Value result;
if (argc == 3 && strcmp(argv[2], "-?") == 0)
{
// Call help locally, help text is returned in an exception
try
{
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
Array params;
(*(*mi).second)(params, true);
}
catch (std::exception& e)
{
result = e.what();
}
}
else
{
// Parameters default to strings // Parameters default to strings
Array params; Array params;
for (int i = 2; i < argc; i++) for (int i = 2; i < argc; i++)
@ -854,7 +902,7 @@ int CommandLineRPC(int argc, char *argv[])
int n = params.size(); int n = params.size();
// //
// Special case other types // Special case non-string parameter types
// //
if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]); if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
@ -872,7 +920,8 @@ int CommandLineRPC(int argc, char *argv[])
if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]); if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]);
// Execute // Execute
Value result = CallRPC(strMethod, params); result = CallRPC(strMethod, params);
}
// Print result // Print result
string strResult = (result.type() == str_type ? result.get_str() : write_string(result, true)); string strResult = (result.type() == str_type ? result.get_str() : write_string(result, true));

View file

@ -19,7 +19,7 @@ class CScript;
class CDataStream; class CDataStream;
class CAutoFile; class CAutoFile;
static const int VERSION = 209; static const int VERSION = 210;
static const char* pszSubVer = ".0"; static const char* pszSubVer = ".0";

9
ui.cpp
View file

@ -1016,6 +1016,11 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60) if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60)
m_statusBar->SetStatusText(" ERROR: ThreadSocketHandler has stopped", 0); m_statusBar->SetStatusText(" ERROR: ThreadSocketHandler has stopped", 0);
// Update receiving address
string strDefaultAddress = PubKeyToAddress(vchDefaultKey);
if (m_textCtrlAddress->GetValue() != strDefaultAddress)
m_textCtrlAddress->SetValue(strDefaultAddress);
} }
@ -2087,7 +2092,9 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
} }
// Send payment tx to seller, with response going to OnReply3 via event handler // Send payment tx to seller, with response going to OnReply3 via event handler
pnode->PushRequest("submitorder", wtx, SendingDialogOnReply3, this); CWalletTx wtxSend = wtx;
wtxSend.fFromMe = false;
pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this);
Status(_("Waiting for confirmation...")); Status(_("Waiting for confirmation..."));
MainFrameRepaint(); MainFrameRepaint();

View file

@ -616,7 +616,7 @@ CSendDialogBase::CSendDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
fgSizer1->Add( 0, 0, 0, wxEXPAND, 5 ); fgSizer1->Add( 0, 0, 0, wxEXPAND, 5 );
m_staticTextInstructions = new wxStaticText( this, wxID_ANY, _("Enter the recipient's IP address (e.g. 123.45.6.7) for online transfer with comments and confirmation, \nor Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L) if recipient is not online."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextInstructions = new wxStaticText( this, wxID_ANY, _("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L) or IP address (e.g. 123.45.6.7)"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextInstructions->Wrap( -1 ); m_staticTextInstructions->Wrap( -1 );
fgSizer1->Add( m_staticTextInstructions, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); fgSizer1->Add( m_staticTextInstructions, 0, wxTOP|wxRIGHT|wxLEFT, 5 );

View file

@ -275,7 +275,7 @@ class CSendDialogBase : public wxDialog
public: public:
CSendDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Send Coins"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 675,312 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); CSendDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Send Coins"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 675,298 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~CSendDialogBase(); ~CSendDialogBase();
}; };

View file

@ -388,7 +388,6 @@ typedef base_uint<256> base_uint256;
// //
// uint160 and uint256 could be implemented as templates, but to keep // uint160 and uint256 could be implemented as templates, but to keep
// compile errors and debugging cleaner, they're copy and pasted. // compile errors and debugging cleaner, they're copy and pasted.
// It's safe to search and replace 160 with 256 and vice versa.
// //
@ -405,6 +404,8 @@ public:
uint160() uint160()
{ {
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
} }
uint160(const basetype& b) uint160(const basetype& b)
@ -517,6 +518,8 @@ public:
uint256() uint256()
{ {
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
} }
uint256(const basetype& b) uint256(const basetype& b)

View file

@ -18,7 +18,7 @@
<property name="relative_path">1</property> <property name="relative_path">1</property>
<property name="use_enum">0</property> <property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property> <property name="use_microsoft_bom">0</property>
<object class="Frame" expanded="1"> <object class="Frame" expanded="0">
<property name="bg">wxSYS_COLOUR_BTNFACE</property> <property name="bg">wxSYS_COLOUR_BTNFACE</property>
<property name="center"></property> <property name="center"></property>
<property name="context_help"></property> <property name="context_help"></property>
@ -3317,7 +3317,7 @@
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">CSendDialogBase</property> <property name="name">CSendDialogBase</property>
<property name="pos"></property> <property name="pos"></property>
<property name="size">675,312</property> <property name="size">675,298</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass"></property> <property name="subclass"></property>
<property name="title">Send Coins</property> <property name="title">Send Coins</property>
@ -3408,7 +3408,7 @@
<property name="font"></property> <property name="font"></property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Enter the recipient&apos;s IP address (e.g. 123.45.6.7) for online transfer with comments and confirmation, &#x0A;or Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L) if recipient is not online.</property> <property name="label">Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L) or IP address (e.g. 123.45.6.7)</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">m_staticTextInstructions</property> <property name="name">m_staticTextInstructions</property>

9
util.h
View file

@ -520,8 +520,13 @@ inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=fa
inline void SetThreadPriority(int nPriority) inline void SetThreadPriority(int nPriority)
{ {
// threads are processes on linux, so PRIO_PROCESS affects just the one thread // It's unclear if it's even possible to change thread priorities on Linux,
setpriority(PRIO_PROCESS, getpid(), nPriority); // but we really and truly need it for the generation threads.
#ifdef PRIO_THREAD
setpriority(PRIO_THREAD, 0, nPriority);
#else
setpriority(PRIO_PROCESS, 0, nPriority);
#endif
} }
inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode) inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode)