diff options
author | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-02-23 22:01:39 +0000 |
---|---|---|
committer | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-02-23 22:01:39 +0000 |
commit | 30158c77e99a099cbdd556bacbac18b431c3870c (patch) | |
tree | 60f2b388dc78f0e25ce873a8ea4487393711b18e | |
parent | ee618d7540107aef543a0b252509b3005a15409c (diff) |
run as daemon without GUI,
hooked wxApp::Initialize to ignore gtk-init-check failure if no GUI,
fork to daemonize,
rpc getinfo, getconnectioncount, getbalance, getgenerate, setgenerate,
-- version 0.2.6
-rw-r--r-- | main.cpp | 15 | ||||
-rw-r--r-- | main.h | 4 | ||||
-rw-r--r-- | rpc.cpp | 134 | ||||
-rw-r--r-- | serialize.h | 2 | ||||
-rw-r--r-- | ui.cpp | 94 | ||||
-rw-r--r-- | util.cpp | 4 | ||||
-rw-r--r-- | util.h | 1 |
7 files changed, 207 insertions, 47 deletions
@@ -1315,11 +1315,10 @@ bool CBlock::AcceptBlock() if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
- // Check that all transactions are finalized (starting around Mar 2010)
- if (nBestHeight > 36000)
- foreach(const CTransaction& tx, vtx)
- if (!tx.IsFinal(nTime))
- return error("AcceptBlock() : contains a non-final transaction");
+ // Check that all transactions are finalized
+ foreach(const CTransaction& tx, vtx)
+ if (!tx.IsFinal(nTime))
+ return error("AcceptBlock() : contains a non-final transaction");
// Check proof of work
if (nBits != GetNextWorkRequired(pindexPrev))
@@ -1336,7 +1335,7 @@ bool CBlock::AcceptBlock() return error("AcceptBlock() : AddToBlockIndex failed");
// Don't relay old inventory during initial block download.
- // Please keep this constant updated to a few thousand below current block count.
+ // Please keep this number updated to a few thousand below current block count.
if (hashBestChain == hash && nBestHeight > 40000)
RelayInventory(CInv(MSG_BLOCK, hash));
@@ -1556,8 +1555,8 @@ bool LoadBlockIndex(bool fAllowNew) CTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
- txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
- txNew.vout[0].nValue = 50 * COIN;
+ txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
+ txNew.vout[0].nValue = 50 * COIN;
CBigNum bnPubKey;
bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704");
txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG;
@@ -1384,6 +1384,9 @@ public: CPrivKey vchPrivKey;
int64 nTimeCreated;
int64 nTimeExpires;
+ string strComment;
+ //// todo: add something to note what created it (user, getnewaddress, change)
+ //// maybe should have a map<string, string> property map
CWalletKey(int64 nTimeExpiresIn=0)
{
@@ -1398,6 +1401,7 @@ public: READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
READWRITE(nTimeExpires);
+ READWRITE(strComment);
)
};
@@ -66,6 +66,17 @@ Value getblocknumber(const Array& params) }
+Value getconnectioncount(const Array& params)
+{
+ if (params.size() != 0)
+ throw runtime_error(
+ "getconnectioncount (no parameters)\n"
+ "Returns the number of connections to other nodes.");
+
+ return (int)vNodes.size();
+}
+
+
Value getdifficulty(const Array& params)
{
if (params.size() != 0)
@@ -85,6 +96,71 @@ Value getdifficulty(const Array& params) }
+Value getbalance(const Array& params)
+{
+ if (params.size() != 0)
+ throw runtime_error(
+ "getbalance (no parameters)\n"
+ "Returns the server's available balance.");
+
+ return ((double)GetBalance() / (double)COIN);
+}
+
+
+Value getgenerate(const Array& params)
+{
+ if (params.size() != 0)
+ throw runtime_error(
+ "getgenerate (no parameters)\n"
+ "Returns true or false.");
+
+ return (bool)fGenerateBitcoins;
+}
+
+
+Value setgenerate(const Array& params)
+{
+ if (params.size() < 1 || params.size() > 2)
+ throw runtime_error(
+ "setgenerate <generate> [genproclimit]\n"
+ "<generate> is true or false to turn generation on or off.\n"
+ "Generation is limited to [genproclimit] processors, -1 is unlimited.");
+
+ bool fGenerate = true;
+ if (params.size() > 0)
+ fGenerate = params[0].get_bool();
+
+ if (params.size() > 1)
+ {
+ int nGenProcLimit = params[1].get_int();
+ fLimitProcessors = (nGenProcLimit != -1);
+ CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
+ if (nGenProcLimit != -1)
+ CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
+ }
+
+ GenerateBitcoins(fGenerate);
+ return Value::null;
+}
+
+
+Value getinfo(const Array& params)
+{
+ if (params.size() != 0)
+ throw runtime_error(
+ "getinfo (no parameters)");
+
+ Object obj;
+ obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN));
+ obj.push_back(Pair("blocks", (int)nBestHeight + 1));
+ obj.push_back(Pair("connections", (int)vNodes.size()));
+ obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
+ obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
+ obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
+ return obj;
+}
+
+
Value getnewaddress(const Array& params)
{
if (params.size() > 1)
@@ -102,8 +178,7 @@ Value getnewaddress(const Array& params) // Generate a new key that is added to wallet
string strAddress = PubKeyToAddress(GenerateNewKey());
- if (params.size() > 0)
- SetAddressBookName(strAddress, strLabel);
+ SetAddressBookName(strAddress, strLabel);
return strAddress;
}
@@ -214,10 +289,10 @@ Value getallreceived(const Array& params) "getallreceived [minconf=1]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n"
"Returns an array of objects containing:\n"
- " \"address\" : bitcoin address\n"
+ " \"address\" : receiving address\n"
" \"amount\" : total amount received by the address\n"
- " \"conf\" : number of confirmations\n"
- " \"label\" : the label set for this address when it was created by getnewaddress");
+ " \"confirmations\" : number of confirmations of the most recent transaction included\n"
+ " \"label\" : the label of the receiving address");
// Minimum confirmations
int nMinDepth = 1;
@@ -235,18 +310,26 @@ Value getallreceived(const Array& params) continue;
int nDepth = wtx.GetDepthInMainChain();
- if (nDepth >= nMinDepth)
+ 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)
{
- foreach(const CTxOut& txout, wtx.vout)
- {
- uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
- if (hash160 == 0 || !mapPubKeys.count(hash160))
- continue;
-
- tallyitem& item = mapTally[hash160];
- item.nAmount += txout.nValue;
- item.nConf = min(item.nConf, nDepth);
- }
+ uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
+ if (hash160 == 0 || !mapPubKeys.count(hash160))
+ continue;
+
+ tallyitem& item = mapTally[hash160];
+ item.nAmount += txout.nValue;
+ item.nConf = min(item.nConf, nDepth);
}
}
}
@@ -264,10 +347,10 @@ Value getallreceived(const Array& params) strLabel = (*mi).second;
Object obj;
- obj.push_back(Pair("address", strAddress));
- obj.push_back(Pair("amount", (double)(*it).second.nAmount / (double)COIN));
- obj.push_back(Pair("conf", (*it).second.nConf));
- obj.push_back(Pair("label", strLabel));
+ 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));
ret.push_back(obj);
}
}
@@ -290,7 +373,12 @@ 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),
@@ -568,9 +656,13 @@ int CommandLineRPC(int argc, char *argv[]) Array params;
for (int i = 2; i < argc; i++)
params.push_back(argv[i]);
+ int n = params.size();
+ //
// Special case other types
- int n = params.size();
+ //
+ 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]);
diff --git a/serialize.h b/serialize.h index fb06f881ca..8fb72a0aab 100644 --- a/serialize.h +++ b/serialize.h @@ -19,7 +19,7 @@ class CScript; class CDataStream;
class CAutoFile;
-static const int VERSION = 205;
+static const int VERSION = 206;
static const char* pszSubVer = ".0";
@@ -26,6 +26,20 @@ int fMinimizeOnClose = true; +int MyMessageBox(const wxString& message, const wxString& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
+{
+ if (fDaemon)
+ {
+ printf("wxMessageBox %s: %s\n", string(caption).c_str(), string(message).c_str());
+ fprintf(stderr, "%s: %s\n", string(caption).c_str(), string(message).c_str());
+ return wxOK;
+ }
+ return wxMessageBox(message, caption, style, parent, x, y);
+}
+#define wxMessageBox MyMessageBox
+
+
+
@@ -209,16 +223,10 @@ void CalledMessageBox(const string& message, const string& caption, int style, w int ThreadSafeMessageBox(const string& message, const string& caption, int style, wxWindow* parent, int x, int y)
{
- if (fDaemon)
- {
- printf("wxMessageBox %s: %s\n", caption.c_str(), message.c_str());
- return wxOK;
- }
-
#ifdef __WXMSW__
return wxMessageBox(message, caption, style, parent, x, y);
#else
- if (wxThread::IsMain())
+ if (wxThread::IsMain() || fDaemon)
{
return wxMessageBox(message, caption, style, parent, x, y);
}
@@ -563,7 +571,7 @@ string SingleLine(const string& strIn) bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
{
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
- int64 nCredit = wtx.GetCredit();
+ int64 nCredit = wtx.GetCredit(true);
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
uint256 hash = wtx.GetHash();
@@ -2571,6 +2579,9 @@ public: bool OnInit2();
int OnExit();
+ // Hook Initialize so we can start without GUI
+ virtual bool Initialize(int& argc, wxChar** argv);
+
// 2nd-level exception handling: we get all the exceptions occurring in any
// event handler here
virtual bool OnExceptionInMainLoop();
@@ -2586,6 +2597,64 @@ public: IMPLEMENT_APP(CMyApp)
+bool CMyApp::Initialize(int& argc, wxChar** argv)
+{
+ if (argc > 1 && argv[1][0] != '-' && (!fWindows || argv[1][0] != '/') &&
+ wxString(argv[1]) != "start")
+ {
+ fCommandLine = true;
+ }
+ else
+ {
+ // wxApp::Initialize will remove environment-specific parameters,
+ // so it's too early to call ParseParameters yet
+ for (int i = 1; i < argc; i++)
+ {
+ wxString str = argv[i];
+ #ifdef __WXMSW__
+ if (str.size() >= 1 && str[0] == '/')
+ str[0] = '-';
+ str = str.MakeLower();
+ #endif
+ // haven't decided which argument to use for this yet
+ if (str == "-daemon" || str == "-d" || str == "start")
+ fDaemon = true;
+ }
+ }
+
+#ifdef __WXGTK__
+ if (fDaemon || fCommandLine)
+ {
+ // Call the original Initialize while suppressing error messages
+ // and ignoring failure. If unable to initialize GTK, it fails
+ // near the end so hopefully the last few things don't matter.
+ {
+ wxLogNull logNo;
+ wxApp::Initialize(argc, argv);
+ }
+
+ if (fDaemon)
+ {
+ fprintf(stdout, "bitcoin server starting\n");
+
+ // Daemonize
+ pid_t pid = fork();
+ if (pid < 0)
+ {
+ fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
+ return false;
+ }
+ if (pid > 0)
+ pthread_exit((void*)0);
+ }
+
+ return true;
+ }
+#endif
+
+ return wxApp::Initialize(argc, argv);
+}
+
bool CMyApp::OnInit()
{
bool fRet = false;
@@ -2650,7 +2719,7 @@ bool CMyApp::OnInit2() //
// Parameters
//
- if (argc > 1 && argv[1][0] != '-' && argv[1][0] != '/')
+ if (fCommandLine)
{
int ret = CommandLineRPC(argc, argv);
exit(ret);
@@ -2696,13 +2765,6 @@ bool CMyApp::OnInit2() if (mapArgs.count("-printtodebugger"))
fPrintToDebugger = true;
- if (mapArgs.count("-daemon") || mapArgs.count("-d"))
- {
- fDaemon = true;
- /// todo: need to fork
- /// should it fork after the bind/single instance stuff?
- }
-
if (!fDebug && !pszSetDataDir[0])
ShrinkDebugFile();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
@@ -13,6 +13,7 @@ bool fPrintToDebugger = false; char pszSetDataDir[MAX_PATH] = "";
bool fShutdown = false;
bool fDaemon = false;
+bool fCommandLine = false;
@@ -500,7 +501,8 @@ void PrintException(std::exception* pex, const char* pszThread) char pszMessage[1000];
FormatException(pszMessage, pex, pszThread);
printf("\n\n************************\n%s\n", pszMessage);
- if (wxTheApp)
+ fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
+ if (wxTheApp && !fDaemon)
wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
throw;
//DebugBreak();
@@ -121,6 +121,7 @@ extern bool fPrintToDebugger; extern char pszSetDataDir[MAX_PATH];
extern bool fShutdown;
extern bool fDaemon;
+extern bool fCommandLine;
void RandAddSeed();
void RandAddSeedPerfmon();
|