Browse Source

flush wallet.dat, multi-proc, reorg options, revert to startup folder shortcut

pull/1/head
s_nakamoto 13 years ago
parent
commit
5210998688
  1. 23
      build.txt
  2. 57
      db.cpp
  3. 3
      db.h
  4. 6
      headers.h
  5. 14
      irc.cpp
  6. 12
      key.h
  7. 152
      main.cpp
  8. 14
      main.h
  9. 4
      makefile
  10. 4
      makefile.vc
  11. 111
      net.cpp
  12. 17
      net.h
  13. 2
      serialize.h
  14. 663
      ui.cpp
  15. 108
      ui.h
  16. 233
      uibase.cpp
  17. 193
      uibase.h
  18. 1581
      uiproject.fbp
  19. 4
      util.cpp

23
readme.txt → build.txt

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
BitCoin v0.1.5 ALPHA
BitCoin v0.1.6 ALPHA
Copyright (c) 2009 Satoshi Nakamoto
Distributed under the MIT/X11 software license, see the accompanying
@ -10,7 +10,7 @@ cryptographic software written by Eric Young (eay@cryptsoft.com). @@ -10,7 +10,7 @@ cryptographic software written by Eric Young (eay@cryptsoft.com).
Compilers Supported
-------------------
MinGW GCC (v3.4.5)
MinGW GCC (currently v3.4.5)
Microsoft Visual C++ 6.0 SP6
@ -31,6 +31,16 @@ Berkeley DB New BSD license with additional requirement that linked software @@ -31,6 +31,16 @@ Berkeley DB New BSD license with additional requirement that linked software
Boost MIT-like license
Notes
-----
The UI layout is edited with wxFormBuilder. Open the project file
uiproject.fbp. It generates uibase.cpp and uibase.h, which define base
classes that do the rote work of constructing all the UI elements.
The release is built with GCC and then "strip bitcoin.exe" to strip the debug
symbols, which reduces the executable size by about 90%.
OpenSSL
-------
Bitcoin does not use any encryption. If you want to do a no-everything
@ -47,7 +57,7 @@ Add this to crypto\err\err_all.c before the ERR_load_crypto_strings line: @@ -47,7 +57,7 @@ Add this to crypto\err\err_all.c before the ERR_load_crypto_strings line:
Edit ms\mingw32.bat and replace the Configure line's parameters with this
no-everything list. You have to put this in the batch file because batch
files can't handle more than 9 parameters.
files can't take more than 9 command line parameters.
perl Configure mingw threads no-rc2 no-rc4 no-rc5 no-idea no-des no-bf no-cast no-aes no-camellia no-seed no-rsa no-dh
Also REM out the following line in ms\mingw32.bat. The build fails after it's
@ -64,7 +74,7 @@ If you want to use it with MSVC, generate the .lib file @@ -64,7 +74,7 @@ If you want to use it with MSVC, generate the .lib file
Berkeley DB
-----------
MinGW with MSYS:
Using MinGW and MSYS:
cd \DB\build_unix
sh ../dist/configure --enable-mingw --enable-cxx
make
@ -72,5 +82,6 @@ make @@ -72,5 +82,6 @@ make
Boost
-----
You may need Boost version 1.35 to build with MSVC 6.0. I couldn't get
version 1.37 to compile with MSVC 6.0.
If you have trouble compiling Boost with Microsoft Visual C++ 6.0, try going
back to Boost version 1.35. It looks like they may be starting to reduce
support for MSVC 6.0.

57
db.cpp

@ -453,11 +453,7 @@ bool CAddrDB::LoadAddresses() @@ -453,11 +453,7 @@ bool CAddrDB::LoadAddresses()
}
}
//// debug print
printf("mapAddresses:\n");
foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
item.second.print();
printf("-----\n");
printf("Loaded %d addresses\n", mapAddresses.size());
// Fix for possible bug that manifests in mapAddresses.count in irc.cpp,
// just need to call count here and it doesn't happen there. The bug was the
@ -501,6 +497,26 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews) @@ -501,6 +497,26 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews)
// CWalletDB
//
CWalletDB::~CWalletDB()
{
// Flush whenever all handles to wallet.dat are closed
Close();
CRITICAL_BLOCK(cs_db)
{
map<string, int>::iterator mi = mapFileUseCount.find(strFile);
if (mi != mapFileUseCount.end())
{
int nRefCount = (*mi).second;
if (nRefCount == 0)
{
dbenv.txn_checkpoint(0, 0, 0);
dbenv.lsn_reset(strFile.c_str(), 0);
mapFileUseCount.erase(mi++);
}
}
}
}
bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
{
vchDefaultKeyRet.clear();
@ -568,34 +584,51 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet) @@ -568,34 +584,51 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
{
ssValue >> vchDefaultKeyRet;
}
else if (strType == "setting") /// or settings or option or options or config?
else if (strType == "setting")
{
string strKey;
ssKey >> strKey;
// Menu state
if (strKey == "fShowGenerated") ssValue >> fShowGenerated;
if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins;
// Options
if (strKey == "nTransactionFee") ssValue >> nTransactionFee;
if (strKey == "addrIncoming") ssValue >> addrIncoming;
if (strKey == "minimizeToTray") ssValue >> minimizeToTray;
if (strKey == "closeToTray") ssValue >> closeToTray;
if (strKey == "startOnSysBoot") ssValue >> startOnSysBoot;
if (strKey == "askBeforeClosing") ssValue >> askBeforeClosing;
if (strKey == "alwaysShowTrayIcon") ssValue >> alwaysShowTrayIcon;
if (strKey == "fLimitProcessors") ssValue >> fLimitProcessors;
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
if (strKey == "fMinimizeOnClose") ssValue >> fMinimizeOnClose;
}
}
}
printf("fShowGenerated = %d\n", fShowGenerated);
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
printf("nTransactionFee = %I64d\n", nTransactionFee);
printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
printf("fMinimizeToTray = %d\n", fMinimizeToTray);
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
// The transaction fee setting won't be needed for many years to come.
// Setting it to zero here in case they set it to something in an earlier version.
if (nTransactionFee != 0)
{
nTransactionFee = 0;
WriteSetting("nTransactionFee", nTransactionFee);
}
return true;
}
bool LoadWallet()
bool LoadWallet(bool& fFirstRunRet)
{
fFirstRunRet = false;
vector<unsigned char> vchDefaultKey;
if (!CWalletDB("cr").LoadWallet(vchDefaultKey))
return false;
fFirstRunRet = vchDefaultKey.empty();
if (mapKeys.count(vchDefaultKey))
{

3
db.h

@ -338,6 +338,7 @@ class CWalletDB : public CDB @@ -338,6 +338,7 @@ class CWalletDB : public CDB
{
public:
CWalletDB(const char* pszMode="r+", bool fTxn=false) : CDB("wallet.dat", pszMode, fTxn) { }
~CWalletDB();
private:
CWalletDB(const CWalletDB&);
void operator=(const CWalletDB&);
@ -412,7 +413,7 @@ public: @@ -412,7 +413,7 @@ public:
bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet);
};
bool LoadWallet();
bool LoadWallet(bool& fFirstRunRet);
inline bool SetAddressBookName(const string& strAddress, const string& strName)
{

6
headers.h

@ -10,11 +10,11 @@ @@ -10,11 +10,11 @@
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0500
#define _WIN32_WINNT 0x0400
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
#define _WIN32_IE 0x0500
#define _WIN32_IE 0x0400
#define WIN32_LEAN_AND_MEAN 1
#include <wx/wx.h>
#include <wx/clipbrd.h>
@ -28,6 +28,8 @@ @@ -28,6 +28,8 @@
#include <windows.h>
#include <winsock2.h>
#include <mswsock.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>

14
irc.cpp

@ -52,7 +52,7 @@ bool DecodeAddress(string str, CAddress& addr) @@ -52,7 +52,7 @@ bool DecodeAddress(string str, CAddress& addr)
static bool Send(SOCKET hSocket, const char* pszSend)
{
if (strstr(pszSend, "PONG") != pszSend)
printf("SENDING: %s\n", pszSend);
printf("IRC SENDING: %s\n", pszSend);
const char* psz = pszSend;
const char* pszEnd = psz + strlen(psz);
while (psz < pszEnd)
@ -145,7 +145,7 @@ bool Wait(int nSeconds) @@ -145,7 +145,7 @@ bool Wait(int nSeconds)
{
if (fShutdown)
return false;
printf("Waiting %d seconds to reconnect to IRC\n", nSeconds);
printf("IRC waiting %d seconds to reconnect\n", nSeconds);
for (int i = 0; i < nSeconds; i++)
{
if (fShutdown)
@ -220,7 +220,6 @@ void ThreadIRCSeed(void* parg) @@ -220,7 +220,6 @@ void ThreadIRCSeed(void* parg)
{
if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')
continue;
printf("IRC %s\n", strLine.c_str());
vector<string> vWords;
ParseString(strLine, ' ', vWords);
@ -235,7 +234,7 @@ void ThreadIRCSeed(void* parg) @@ -235,7 +234,7 @@ void ThreadIRCSeed(void* parg)
// index 7 is limited to 16 characters
// could get full length name at index 10, but would be different from join messages
strcpy(pszName, vWords[7].c_str());
printf("GOT WHO: [%s] ", pszName);
printf("IRC got who\n");
}
if (vWords[1] == "JOIN" && vWords[0].size() > 1)
@ -244,7 +243,7 @@ void ThreadIRCSeed(void* parg) @@ -244,7 +243,7 @@ void ThreadIRCSeed(void* parg)
strcpy(pszName, vWords[0].c_str() + 1);
if (strchr(pszName, '!'))
*strchr(pszName, '!') = '\0';
printf("GOT JOIN: [%s] ", pszName);
printf("IRC got join\n");
}
if (pszName[0] == 'u')
@ -254,7 +253,7 @@ void ThreadIRCSeed(void* parg) @@ -254,7 +253,7 @@ void ThreadIRCSeed(void* parg)
{
CAddrDB addrdb;
if (AddAddress(addrdb, addr))
printf("new ");
printf("IRC got new address\n");
else
{
// make it try connecting again
@ -262,14 +261,13 @@ void ThreadIRCSeed(void* parg) @@ -262,14 +261,13 @@ void ThreadIRCSeed(void* parg)
if (mapAddresses.count(addr.GetKey()))
mapAddresses[addr.GetKey()].nLastFailed = 0;
}
addr.print();
CRITICAL_BLOCK(cs_mapIRCAddresses)
mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
}
else
{
printf("decode failed\n");
printf("IRC decode failed\n");
}
}
}

12
key.h

@ -44,6 +44,7 @@ class CKey @@ -44,6 +44,7 @@ class CKey
{
protected:
EC_KEY* pkey;
bool fSet;
public:
CKey()
@ -51,6 +52,7 @@ public: @@ -51,6 +52,7 @@ public:
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
if (pkey == NULL)
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
fSet = false;
}
CKey(const CKey& b)
@ -58,12 +60,14 @@ public: @@ -58,12 +60,14 @@ public:
pkey = EC_KEY_dup(b.pkey);
if (pkey == NULL)
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
fSet = b.fSet;
}
CKey& operator=(const CKey& b)
{
if (!EC_KEY_copy(pkey, b.pkey))
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
fSet = b.fSet;
return (*this);
}
@ -72,10 +76,16 @@ public: @@ -72,10 +76,16 @@ public:
EC_KEY_free(pkey);
}
bool IsNull() const
{
return !fSet;
}
void MakeNewKey()
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
fSet = true;
}
bool SetPrivKey(const CPrivKey& vchPrivKey)
@ -83,6 +93,7 @@ public: @@ -83,6 +93,7 @@ public:
const unsigned char* pbegin = &vchPrivKey[0];
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
return false;
fSet = true;
return true;
}
@ -103,6 +114,7 @@ public: @@ -103,6 +114,7 @@ public:
const unsigned char* pbegin = &vchPubKey[0];
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
return false;
fSet = true;
return true;
}

152
main.cpp

@ -34,7 +34,7 @@ map<uint256, CDataStream*> mapOrphanTransactions; @@ -34,7 +34,7 @@ map<uint256, CDataStream*> mapOrphanTransactions;
multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
map<uint256, CWalletTx> mapWallet;
vector<pair<uint256, bool> > vWalletUpdated;
vector<uint256> vWalletUpdated;
CCriticalSection cs_mapWallet;
map<vector<unsigned char>, CPrivKey> mapKeys;
@ -46,9 +46,12 @@ string strSetDataDir; @@ -46,9 +46,12 @@ string strSetDataDir;
int nDropMessagesTest = 0;
// Settings
int fGenerateBitcoins;
int fGenerateBitcoins = false;
int64 nTransactionFee = 0;
CAddress addrIncoming;
int fLimitProcessors = false;
int nLimitProcessors = 1;
@ -135,7 +138,7 @@ bool AddToWallet(const CWalletTx& wtxIn) @@ -135,7 +138,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
return false;
// Notify UI
vWalletUpdated.push_back(make_pair(hash, fInsertedNew));
vWalletUpdated.push_back(hash);
}
// Refresh UI
@ -1126,6 +1129,9 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) @@ -1126,6 +1129,9 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
}
}
// Notify UI to update prev block coinbase if it was ours
vWalletUpdated.push_back(hashBestChain);
// New best link
hashBestChain = hash;
pindexBest = pindexNew;
@ -1702,7 +1708,7 @@ bool ProcessMessages(CNode* pfrom) @@ -1702,7 +1708,7 @@ bool ProcessMessages(CNode* pfrom)
}
CATCH_PRINT_EXCEPTION("ProcessMessage()")
if (!fRet)
printf("ProcessMessage(%s, %d bytes) from %s to %s FAILED\n", strCommand.c_str(), nMessageSize, pfrom->addr.ToString().c_str(), addrLocalHost.ToString().c_str());
printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize);
}
vRecv.Compact();
@ -1715,10 +1721,7 @@ bool ProcessMessages(CNode* pfrom) @@ -1715,10 +1721,7 @@ bool ProcessMessages(CNode* pfrom)
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
static map<unsigned int, vector<unsigned char> > mapReuseKey;
printf("received: %-12s (%d bytes) ", strCommand.c_str(), vRecv.size());
for (int i = 0; i < min(vRecv.size(), (unsigned int)20); i++)
printf("%02x ", vRecv[i] & 0xff);
printf("\n");
printf("received: %-12s (%d bytes)\n", strCommand.c_str(), vRecv.size());
if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
{
printf("dropmessages DROPPING RECV MESSAGE\n");
@ -1759,7 +1762,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1759,7 +1762,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
}
printf("version message: %s has version %d, addrMe=%s\n", pfrom->addr.ToString().c_str(), pfrom->nVersion, addrMe.ToString().c_str());
printf("version message: version %d\n", pfrom->nVersion);
}
@ -1775,13 +1778,24 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1775,13 +1778,24 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vector<CAddress> vAddr;
vRecv >> vAddr;
// Clear addrknown lists periodically to allow refresh broadcasts
static int64 nLastClearedAddrKnown;
if (nLastClearedAddrKnown < GetAdjustedTime() - 24 * 60 * 60)
{
nLastClearedAddrKnown = GetAdjustedTime();
CRITICAL_BLOCK(cs_vNodes)
foreach(CNode* pnode, vNodes)
pnode->setAddrKnown.clear();
}
// Store the new addresses
CAddrDB addrdb;
foreach(const CAddress& addr, vAddr)
{
if (fShutdown)
return true;
if (AddAddress(addrdb, addr))
AddAddress(addrdb, addr);
if (addr.IsRoutable() && addr.ip != addrLocalHost.ip)
{
// Put on lists to send to other nodes
pfrom->setAddrKnown.insert(addr);
@ -1989,8 +2003,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1989,8 +2003,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (fShutdown)
return true;
const CAddress& addr = item.second;
//// will need this if we lose IRC
//if (addr.nTime > nSince || (rand() % nSize) < 500)
if (addr.nTime > nSince)
pfrom->vAddrToSend.push_back(addr);
}
@ -2132,9 +2144,11 @@ bool SendMessages(CNode* pto) @@ -2132,9 +2144,11 @@ bool SendMessages(CNode* pto)
while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
{
const CInv& inv = (*pto->mapAskFor.begin()).second;
printf("sending getdata: %s\n", inv.ToString().c_str());
if (!AlreadyHave(txdb, inv))
{
printf("sending getdata: %s\n", inv.ToString().c_str());
vAskFor.push_back(inv);
}
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
if (!vAskFor.empty())
@ -2162,6 +2176,49 @@ bool SendMessages(CNode* pto) @@ -2162,6 +2176,49 @@ bool SendMessages(CNode* pto)
// BitcoinMiner
//
void GenerateBitcoins(bool fGenerate)
{
if (fGenerateBitcoins != fGenerate)
{
fGenerateBitcoins = fGenerate;
CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
MainFrameRepaint();
}
if (fGenerateBitcoins)
{
int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
printf("%d processors\n", nProcessors);
if (nProcessors < 1)
nProcessors = 1;
if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors;
int nAddThreads = nProcessors - vnThreadsRunning[3];
printf("starting %d bitcoinminer threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
}
}
void ThreadBitcoinMiner(void* parg)
{
vnThreadsRunning[3]++;
CheckForShutdown(3);
try
{
bool fRet = BitcoinMiner();
printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
vnThreadsRunning[3]--;
}
catch (std::exception& e) {
vnThreadsRunning[3]--;
PrintException(&e, "ThreadBitcoinMiner()");
} catch (...) {
vnThreadsRunning[3]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
}
int FormatHashBlocks(void* pbuffer, unsigned int len)
{
unsigned char* pdata = (unsigned char*)pbuffer;
@ -2210,13 +2267,13 @@ void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout) @@ -2210,13 +2267,13 @@ void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout)
bool BitcoinMiner()
{
printf("BitcoinMiner started\n");
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
CKey key;
key.MakeNewKey();
CBigNum bnExtraNonce = 0;
while (fGenerateBitcoins)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
Sleep(50);
CheckForShutdown(3);
while (vNodes.empty())
@ -2338,7 +2395,6 @@ bool BitcoinMiner() @@ -2338,7 +2395,6 @@ bool BitcoinMiner()
BlockSHA256(&tmp.block, nBlocks0, &tmp.hash1);
BlockSHA256(&tmp.hash1, nBlocks1, &hash);
if (hash <= hashTarget)
{
pblock->nNonce = tmp.block.nNonce;
@ -2352,6 +2408,12 @@ bool BitcoinMiner() @@ -2352,6 +2408,12 @@ bool BitcoinMiner()
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
CRITICAL_BLOCK(cs_main)
{
if (pindexPrev != pindexBest)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
break;
}
// Save key
if (!AddKey(key))
return false;
@ -2368,7 +2430,7 @@ bool BitcoinMiner() @@ -2368,7 +2430,7 @@ bool BitcoinMiner()
}
// Update nTime every few seconds
if ((++tmp.block.nNonce & 0x3ffff) == 0)
if ((++tmp.block.nNonce & 0xffff) == 0)
{
CheckForShutdown(3);
if (tmp.block.nNonce == 0)
@ -2379,6 +2441,8 @@ bool BitcoinMiner() @@ -2379,6 +2441,8 @@ bool BitcoinMiner()
break;
if (!fGenerateBitcoins)
break;
if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
return true;
tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
}
}
@ -2538,7 +2602,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet) @@ -2538,7 +2602,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet)
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet)
{
nFeeRequiredRet = 0;
CRITICAL_BLOCK(cs_main)
@ -2565,30 +2629,28 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in @@ -2565,30 +2629,28 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in
foreach(CWalletTx* pcoin, setCoins)
nValueIn += pcoin->GetCredit();
// Fill vout[0] to the payee
wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
// Fill a vout to the payee
bool fChangeFirst = GetRand(2);
if (!fChangeFirst)
wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
// Fill vout[1] back to self with any change
// Fill a vout back to self with any change
if (nValueIn > nValue)
{
/// todo: for privacy, should randomize the order of outputs,
// would also have to use a new key for the change.
// Use the same key as one of the coins
vector<unsigned char> vchPubKey;
CTransaction& txFirst = *(*setCoins.begin());
foreach(const CTxOut& txout, txFirst.vout)
if (txout.IsMine())
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
break;
if (vchPubKey.empty())
return false;
// New private key
if (keyRet.IsNull())
keyRet.MakeNewKey();
// Fill vout[1] to ourself
// Fill a vout to ourself
CScript scriptPubKey;
scriptPubKey << vchPubKey << OP_CHECKSIG;
scriptPubKey << keyRet.GetPubKey() << OP_CHECKSIG;
wtxNew.vout.push_back(CTxOut(nValueIn - nValue, scriptPubKey));
}
// Fill a vout to the payee
if (fChangeFirst)
wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
// Fill vin
foreach(CWalletTx* pcoin, setCoins)
for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
@ -2621,13 +2683,24 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in @@ -2621,13 +2683,24 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in
}
// Call after CreateTransaction unless you want to abort
bool CommitTransactionSpent(const CWalletTx& wtxNew)
bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
{
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
{
//// todo: make this transactional, never want to add a transaction
//// without marking spent transactions
//// todo: eventually should make this transactional, never want to add a
//// transaction without marking spent transactions, although the risk of
//// interruption during this step is remote.
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
// maybe makes sense; please don't do it anywhere else. Keeping databases
// open longer than necessary can create deadlocks.
CWalletDB walletdb("r");
// Add the change's private key to wallet
if (!key.IsNull() && !AddKey(key))
throw runtime_error("CommitTransactionSpent() : AddKey failed\n");
// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
@ -2641,7 +2714,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew) @@ -2641,7 +2714,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew)
{
pcoin->fSpent = true;
pcoin->WriteToDisk();
vWalletUpdated.push_back(make_pair(pcoin->GetHash(), false));
vWalletUpdated.push_back(pcoin->GetHash());
}
}
MainFrameRepaint();
@ -2655,8 +2728,9 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) @@ -2655,8 +2728,9 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
{
CRITICAL_BLOCK(cs_main)
{
CKey key;
int64 nFeeRequired;
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, nFeeRequired))
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, key, nFeeRequired))
{
string strError;
if (nValue + nFeeRequired > GetBalance())
@ -2666,7 +2740,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) @@ -2666,7 +2740,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
wxMessageBox(strError, "Sending...");
return error("SendMoney() : %s\n", strError.c_str());
}
if (!CommitTransactionSpent(wtxNew))
if (!CommitTransactionSpent(wtxNew, key))
{
wxMessageBox("Error finalizing transaction ", "Sending...");
return error("SendMoney() : Error finalizing transaction");

14
main.h

@ -41,6 +41,9 @@ extern int nDropMessagesTest; @@ -41,6 +41,9 @@ extern int nDropMessagesTest;
extern int fGenerateBitcoins;
extern int64 nTransactionFee;
extern CAddress addrIncoming;
extern int fLimitProcessors;
extern int nLimitProcessors;
@ -58,14 +61,17 @@ void ReacceptWalletTransactions(); @@ -58,14 +61,17 @@ void ReacceptWalletTransactions();
void RelayWalletTransactions();
bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree();
bool BitcoinMiner();
bool ProcessMessages(CNode* pfrom);
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
bool SendMessages(CNode* pto);
int64 GetBalance();
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& txNew, int64& nFeeRequiredRet);
bool CommitTransactionSpent(const CWalletTx& wtxNew);
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key);
bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
void GenerateBitcoins(bool fGenerate);
void ThreadBitcoinMiner(void* parg);
bool BitcoinMiner();
@ -1320,7 +1326,7 @@ public: @@ -1320,7 +1326,7 @@ public:
extern map<uint256, CTransaction> mapTransactions;
extern map<uint256, CWalletTx> mapWallet;
extern vector<pair<uint256, bool> > vWalletUpdated;
extern vector<uint256> vWalletUpdated;
extern CCriticalSection cs_mapWallet;
extern map<vector<unsigned char>, CPrivKey> mapKeys;
extern map<uint160, vector<unsigned char> > mapPubKeys;

4
makefile

@ -12,7 +12,7 @@ ifeq "$(BUILD)" "debug" @@ -12,7 +12,7 @@ ifeq "$(BUILD)" "debug"
D=d
# note: gcc 3.x profile doesn't work
#DEBUGFLAGS=-O0 -g -pg -D__WXDEBUG__
DEBUGFLAGS=-g -D__WXDEBUG__ -Wall -Wextra
DEBUGFLAGS=-g -D__WXDEBUG__
endif
@ -23,7 +23,7 @@ LIBS= \ @@ -23,7 +23,7 @@ LIBS= \
-l db_cxx \
-l eay32 \
-l wxmsw28$(D)_richtext -l wxmsw28$(D)_html -l wxmsw28$(D)_core -l wxmsw28$(D)_adv -l wxbase28$(D) -l wxtiff$(D) -l wxjpeg$(D) -l wxpng$(D) -l wxzlib$(D) -l wxregex$(D) -l wxexpat$(D) \
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h

4
makefile.vc

@ -18,8 +18,8 @@ LIBPATHS=/LIBPATH:"/DB/build_windows/$(BUILD)" /LIBPATH:"/OpenSSL/out" /LIBPATH: @@ -18,8 +18,8 @@ LIBPATHS=/LIBPATH:"/DB/build_windows/$(BUILD)" /LIBPATH:"/OpenSSL/out" /LIBPATH:
LIBS= \
libdb47s$(D).lib \
libeay32.lib \
wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib
wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxmsw28$(D)_adv.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
CFLAGS=/c /nologo /Ob0 /MD$(D) /EHsc /GR /Zm300 /YX /Fpobj/headers.pch $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h

111
net.cpp

@ -23,7 +23,8 @@ CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices); @@ -23,7 +23,8 @@ CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
CNode* pnodeLocalHost = &nodeLocalHost;
bool fShutdown = false;
array<bool, 10> vfThreadRunning;
array<int, 10> vnThreadsRunning;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
map<vector<unsigned char>, CAddress> mapAddresses;
@ -57,7 +58,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) @@ -57,7 +58,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
if (fProxy)
{
printf("Proxy connecting to %s\n", addrConnect.ToString().c_str());
printf("Proxy connecting %s\n", addrConnect.ToStringLog().c_str());
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
@ -81,7 +82,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) @@ -81,7 +82,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
closesocket(hSocket);
return error("Proxy returned error %d\n", pchRet[1]);
}
printf("Proxy connection established %s\n", addrConnect.ToString().c_str());
printf("Proxy connection established %s\n", addrConnect.ToStringLog().c_str());
}
hSocketRet = hSocket;
@ -219,6 +220,13 @@ bool AddAddress(CAddrDB& addrdb, const CAddress& addr) @@ -219,6 +220,13 @@ bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
addrdb.WriteAddress(addrFound);
return true;
}
else if (addrFound.nTime < GetAdjustedTime() - 24 * 60 * 60)
{
// Periodically update most recently seen time
addrFound.nTime = GetAdjustedTime();
addrdb.WriteAddress(addrFound);
return false;
}
}
}
return false;
@ -373,14 +381,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) @@ -373,14 +381,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
}
/// debug print
printf("trying %s\n", addrConnect.ToString().c_str());
printf("trying connection %s\n", addrConnect.ToStringLog().c_str());
// Connect
SOCKET hSocket;
if (ConnectSocket(addrConnect, hSocket))
{
/// debug print
printf("connected %s\n", addrConnect.ToString().c_str());
printf("connected %s\n", addrConnect.ToStringLog().c_str());
// Set to nonblocking
u_long nOne = 1;
@ -410,7 +418,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) @@ -410,7 +418,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
void CNode::Disconnect()
{
printf("disconnecting node %s\n", addr.ToString().c_str());
printf("disconnecting node %s\n", addr.ToStringLog().c_str());
closesocket(hSocket);
@ -450,14 +458,20 @@ void ThreadSocketHandler(void* parg) @@ -450,14 +458,20 @@ void ThreadSocketHandler(void* parg)
loop
{
vfThreadRunning[0] = true;
vnThreadsRunning[0] = true;
CheckForShutdown(0);
try
{
ThreadSocketHandler2(parg);
vnThreadsRunning[0] = false;
}
catch (std::exception& e) {
vnThreadsRunning[0] = false;
PrintException(&e, "ThreadSocketHandler()");
} catch (...) {
vnThreadsRunning[0] = false;
PrintException(NULL, "ThreadSocketHandler()");
}
CATCH_PRINT_EXCEPTION("ThreadSocketHandler()")
vfThreadRunning[0] = false;
Sleep(5000);
}
}
@ -548,9 +562,9 @@ void ThreadSocketHandler2(void* parg) @@ -548,9 +562,9 @@ void ThreadSocketHandler2(void* parg)
}
}
vfThreadRunning[0] = false;
vnThreadsRunning[0] = false;
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
vfThreadRunning[0] = true;
vnThreadsRunning[0] = true;
CheckForShutdown(0);
if (nSelect == SOCKET_ERROR)
{
@ -590,7 +604,7 @@ void ThreadSocketHandler2(void* parg) @@ -590,7 +604,7 @@ void ThreadSocketHandler2(void* parg)
}
else
{
printf("accepted connection from %s\n", addr.ToString().c_str());
printf("accepted connection %s\n", addr.ToStringLog().c_str());
CNode* pnode = new CNode(hSocket, addr, true);
pnode->AddRef();
CRITICAL_BLOCK(cs_vNodes)
@ -697,14 +711,20 @@ void ThreadOpenConnections(void* parg) @@ -697,14 +711,20 @@ void ThreadOpenConnections(void* parg)
loop
{
vfThreadRunning[1] = true;
vnThreadsRunning[1] = true;
CheckForShutdown(1);
try
{
ThreadOpenConnections2(parg);
vnThreadsRunning[1] = false;
}
catch (std::exception& e) {
vnThreadsRunning[1] = false;
PrintException(&e, "ThreadOpenConnections()");
} catch (...) {
vnThreadsRunning[1] = false;
PrintException(NULL, "ThreadOpenConnections()");
}
CATCH_PRINT_EXCEPTION("ThreadOpenConnections()")
vfThreadRunning[1] = false;
Sleep(5000);
}
}
@ -720,14 +740,14 @@ void ThreadOpenConnections2(void* parg) @@ -720,14 +740,14 @@ void ThreadOpenConnections2(void* parg)
loop
{
// Wait
vfThreadRunning[1] = false;
vnThreadsRunning[1] = false;
Sleep(500);
while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
{
CheckForShutdown(1);
Sleep(2000);
}
vfThreadRunning[1] = true;
vnThreadsRunning[1] = true;
CheckForShutdown(1);
@ -823,9 +843,9 @@ void ThreadOpenConnections2(void* parg) @@ -823,9 +843,9 @@ void ThreadOpenConnections2(void* parg)
if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
continue;
vfThreadRunning[1] = false;
vnThreadsRunning[1] = false;
CNode* pnode = ConnectNode(addrConnect);
vfThreadRunning[1] = true;
vnThreadsRunning[1] = true;
CheckForShutdown(1);
if (!pnode)
continue;
@ -867,14 +887,20 @@ void ThreadMessageHandler(void* parg) @@ -867,14 +887,20 @@ void ThreadMessageHandler(void* parg)
loop
{
vfThreadRunning[2] = true;
vnThreadsRunning[2] = true;
CheckForShutdown(2);
try
{
ThreadMessageHandler2(parg);
vnThreadsRunning[2] = false;
}
catch (std::exception& e) {
vnThreadsRunning[2] = false;
PrintException(&e, "ThreadMessageHandler()");
} catch (...) {
vnThreadsRunning[2] = false;
PrintException(NULL, "ThreadMessageHandler()");
}
CATCH_PRINT_EXCEPTION("ThreadMessageHandler()")
vfThreadRunning[2] = false;
Sleep(5000);
}
}
@ -905,9 +931,9 @@ void ThreadMessageHandler2(void* parg) @@ -905,9 +931,9 @@ void ThreadMessageHandler2(void* parg)
}
// Wait and allow messages to bunch up
vfThreadRunning[2] = false;
vnThreadsRunning[2] = false;
Sleep(100);
vfThreadRunning[2] = true;
vnThreadsRunning[2] = true;
CheckForShutdown(2);
}
}
@ -920,29 +946,6 @@ void ThreadMessageHandler2(void* parg) @@ -920,29 +946,6 @@ void ThreadMessageHandler2(void* parg)
//// todo: start one thread per processor, use getenv("NUMBER_OF_PROCESSORS")
void ThreadBitcoinMiner(void* parg)
{
vfThreadRunning[3] = true;
CheckForShutdown(3);
try
{
bool fRet = BitcoinMiner();
printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
}
CATCH_PRINT_EXCEPTION("BitcoinMiner()")
vfThreadRunning[3] = false;
}
bool StartNode(string& strError)
{
@ -1067,17 +1070,17 @@ bool StopNode() @@ -1067,17 +1070,17 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
while (vfThreadRunning[0] || vfThreadRunning[2] || vfThreadRunning[3])
while (vnThreadsRunning[0] || vnThreadsRunning[2] || vnThreadsRunning[3])
{
if (GetTime() - nStart > 15)
break;
Sleep(20);
}
if (vfThreadRunning[0]) printf("ThreadSocketHandler still running\n");
if (vfThreadRunning[1]) printf("ThreadOpenConnections still running\n");
if (vfThreadRunning[2]) printf("ThreadMessageHandler still running\n");
if (vfThreadRunning[3]) printf("ThreadBitcoinMiner still running\n");
while (vfThreadRunning[2])
if (vnThreadsRunning[0]) printf("ThreadSocketHandler still running\n");
if (vnThreadsRunning[1]) printf("ThreadOpenConnections still running\n");
if (vnThreadsRunning[2]) printf("ThreadMessageHandler still running\n");
if (vnThreadsRunning[3]) printf("ThreadBitcoinMiner still running\n");
while (vnThreadsRunning[2])
Sleep(20);
Sleep(50);
@ -1091,7 +1094,7 @@ void CheckForShutdown(int n) @@ -1091,7 +1094,7 @@ void CheckForShutdown(int n)
if (fShutdown)
{
if (n != -1)
vfThreadRunning[n] = false;
vnThreadsRunning[n] = false;
if (n == 0)
foreach(CNode* pnode, vNodes)
closesocket(pnode->hSocket);

17
net.h

@ -20,8 +20,6 @@ enum @@ -20,8 +20,6 @@ enum
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
bool GetMyExternalIP(unsigned int& ipRet);
bool AddAddress(CAddrDB& addrdb, const CAddress& addr);
@ -29,7 +27,6 @@ CNode* FindNode(unsigned int ip); @@ -29,7 +27,6 @@ CNode* FindNode(unsigned int ip);
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
bool AnySubscribed(unsigned int nChannel);
void ThreadBitcoinMiner(void* parg);
bool StartNode(string& strError=REF(string()));
bool StopNode();
void CheckForShutdown(int n);
@ -206,7 +203,7 @@ public: @@ -206,7 +203,7 @@ public:
READWRITE(nTime);
}
READWRITE(nServices);
READWRITE(FLATDATA(pchReserved));
READWRITE(FLATDATA(pchReserved)); // for IPv6
READWRITE(ip);
READWRITE(port);
)
@ -280,10 +277,14 @@ public: @@ -280,10 +277,14 @@ public:
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
}
string ToStringLog() const
{
return "";
}
string ToString() const
{
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
//return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
}
void print() const
@ -416,7 +417,7 @@ extern uint64 nLocalServices; @@ -416,7 +417,7 @@ extern uint64 nLocalServices;
extern CAddress addrLocalHost;
extern CNode* pnodeLocalHost;
extern bool fShutdown;
extern array<bool, 10> vfThreadRunning;
extern array<int, 10> vnThreadsRunning;
extern vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;
extern map<vector<unsigned char>, CAddress> mapAddresses;
@ -599,9 +600,7 @@ public: @@ -599,9 +600,7 @@ public:
unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
printf("(%d bytes) ", nSize);
//for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++)
// printf("%02x ", vSend[i] & 0xff);
printf("(%d bytes) ", nSize);
printf("\n");
nPushPos = -1;

2
serialize.h

@ -19,7 +19,7 @@ class CScript; @@ -19,7 +19,7 @@ class CScript;
class CDataStream;
class CAutoFile;
static const int VERSION = 105;
static const int VERSION = 106;

663
ui.cpp

@ -7,6 +7,13 @@ @@ -7,6 +7,13 @@
#include <crtdbg.h>
#endif
void ThreadRequestProductDetails(void* parg);
void ThreadRandSendTest(void* parg);
bool GetStartOnSystemStartup();
void SetStartOnSystemStartup(bool fAutoStart);
DEFINE_EVENT_TYPE(wxEVT_CROSSTHREADCALL)
DEFINE_EVENT_TYPE(wxEVT_REPLY1)
DEFINE_EVENT_TYPE(wxEVT_REPLY2)
@ -16,22 +23,21 @@ DEFINE_EVENT_TYPE(wxEVT_TABLEUPDATED) @@ -16,22 +23,21 @@ DEFINE_EVENT_TYPE(wxEVT_TABLEUPDATED)
DEFINE_EVENT_TYPE(wxEVT_TABLEDELETED)
CMainFrame* pframeMain = NULL;
CMyTaskBarIcon* ptaskbaricon = NULL;
map<string, string> mapAddressBook;
CBitcoinTBIcon* taskBarIcon = NULL; // Tray icon
void ThreadRequestProductDetails(void* parg);
void ThreadRandSendTest(void* parg);
map<string, string> mapArgs;
bool fRandSendTest = false;
void RandSend();
extern int g_isPainting;
// UI settings and their default values
int minimizeToTray = 1;
int closeToTray = 1;
int startOnSysBoot = 1;
int askBeforeClosing = 1;
int alwaysShowTrayIcon = 1;
// Settings
int fShowGenerated = true;
int fMinimizeToTray = true;
int fMinimizeOnClose = true;
@ -282,7 +288,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) @@ -282,7 +288,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
m_listCtrl->SetFocus();
SetIcon(wxICON(bitcoin));
m_menuOptions->Check(wxID_OPTIONSGENERATEBITCOINS, fGenerateBitcoins);
ptaskbaricon = new CMyTaskBarIcon();
// Init toolbar with transparency masked bitmaps
m_toolBar->ClearTools();
@ -327,7 +333,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) @@ -327,7 +333,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
//m_listCtrlOrdersReceived->InsertColumn(4, "", wxLIST_FORMAT_LEFT, 100);
// Init status bar
int pnWidths[3] = { -100, 81, 286 };
int pnWidths[3] = { -100, 88, 290 };
m_statusBar->SetFieldsCount(3, pnWidths);
// Fill your address text box
@ -342,6 +348,8 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) @@ -342,6 +348,8 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
CMainFrame::~CMainFrame()
{
pframeMain = NULL;
delete ptaskbaricon;
ptaskbaricon = NULL;
}
void Shutdown(void* parg)
@ -362,28 +370,24 @@ void Shutdown(void* parg) @@ -362,28 +370,24 @@ void Shutdown(void* parg)
void CMainFrame::OnClose(wxCloseEvent& event)
{
if (closeToTray && event.CanVeto()) {
event.Veto();
SendToTray();
}
else if (!event.CanVeto() || !askBeforeClosing || wxMessageBox("Quit program?", "Confirm", wxYES_NO, this) == wxYES) {
delete taskBarIcon;
Destroy();
_beginthread(Shutdown, 0, NULL);
}
if (fMinimizeToTray && fMinimizeOnClose && event.CanVeto() && !IsIconized())
{
// Divert close to minimize
event.Veto();
Iconize(true);
}
else
{
Destroy();
_beginthread(Shutdown, 0, NULL);
}
}
void CMainFrame::OnIconize(wxIconizeEvent& event)
{
if (minimizeToTray) {
SendToTray();
}
}
void CMainFrame::SendToTray()
{
Hide();
taskBarIcon->Show();
// Hide the task bar button when minimized.
// Event is sent when the frame is minimized or restored.
Show(!fMinimizeToTray || !event.Iconized());
}
void CMainFrame::OnMouseEvents(wxMouseEvent& event)
@ -405,25 +409,21 @@ void CMainFrame::InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSo @@ -405,25 +409,21 @@ void CMainFrame::InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSo
string str0 = strSort;
long nData = *(long*)&hashKey;
if (fNew)
// Find item
if (!fNew && nIndex == -1)
{
while ((nIndex = m_listCtrl->FindItem(nIndex, nData)) != -1)
if (GetItemText(m_listCtrl, nIndex, 1) == hashKey.ToString())
break;
}
// fNew is for blind insert, only use if you're sure it's new
if (fNew || nIndex == -1)
{
nIndex = m_listCtrl->InsertItem(0, str0);
}
else
{
if (nIndex == -1)
{
// Find item
while ((nIndex = m_listCtrl->FindItem(nIndex, nData)) != -1)
if (GetItemText(m_listCtrl, nIndex, 1) == hashKey.ToString())
break;
if (nIndex == -1)
{
printf("CMainFrame::InsertLine : Couldn't find item to be updated\n");
return;
}
}
// If sort key changed, must delete and reinsert to make it relocate
if (GetItemText(m_listCtrl, nIndex, 0) != str0)
{
@ -484,6 +484,28 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -484,6 +484,28 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
string strStatus = FormatTxStatus(wtx);
map<string, string> mapValue = wtx.mapValue;
// Filter
if (wtx.IsCoinBase())
{
// View->Show Generated
if (!fShowGenerated)
return;
// Don't show generated coin until confirmed by at least one block after it
// so we don't get the user's hopes up until it looks like it's probably accepted.
//
// It is not an error when generated blocks are not accepted. By design,
// some percentage of blocks, like 10% or more, will end up not accepted.
// This is the normal mechanism by which the network copes with latency.