Browse Source

addr relaying fixes, proxy option and privacy patches, detect connect to self, non-final tx locktime changes, fix hide unconfirmed generated

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@18 1a98c847-1fd6-4fd8-948a-caf3550aa51b
pull/1/head
s_nakamoto 13 years ago
parent
commit
dd519206a6
  1. 12
      build.txt
  2. 19
      db.cpp
  3. 2
      headers.h
  4. 10
      irc.cpp
  5. 2
      key.h
  6. 71
      main.cpp
  7. 16
      main.h
  8. 4
      makefile
  9. 173
      net.cpp
  10. 131
      net.h
  11. 2
      serialize.h
  12. 84
      strlcpy.h
  13. 223
      ui.cpp
  14. 8
      ui.h
  15. 51
      uibase.cpp
  16. 98
      uibase.h
  17. 308
      uiproject.fbp
  18. 170
      util.cpp
  19. 164
      util.h

12
build.txt

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
BitCoin v0.1.6 ALPHA
BitCoin v0.1.6 BETA
Copyright (c) 2009 Satoshi Nakamoto
Distributed under the MIT/X11 software license, see the accompanying
@ -19,10 +19,10 @@ Dependencies @@ -19,10 +19,10 @@ Dependencies
Libraries you need to obtain separately to build:
default path download
wxWidgets \wxWidgets http://www.wxwidgets.org/downloads/
OpenSSL \OpenSSL http://www.openssl.org/source/
Berkeley DB \DB http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \Boost http://www.boost.org/users/download/
wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/
OpenSSL \openssl http://www.openssl.org/source/
Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \boost http://www.boost.org/users/download/
Their licenses:
wxWidgets LGPL 2.1 with very liberal exceptions
@ -75,7 +75,7 @@ If you want to use it with MSVC, generate the .lib file @@ -75,7 +75,7 @@ If you want to use it with MSVC, generate the .lib file
Berkeley DB
-----------
Using MinGW and MSYS:
cd \DB\build_unix
cd \db\build_unix
sh ../dist/configure --enable-mingw --enable-cxx
make

19
db.cpp

@ -121,10 +121,12 @@ void CDB::Close() @@ -121,10 +121,12 @@ void CDB::Close()
pdb->close(0);
delete pdb;
pdb = NULL;
dbenv.txn_checkpoint(0, 0, 0);
CRITICAL_BLOCK(cs_db)
{
dbenv.txn_checkpoint(0, 0, 0);
--mapFileUseCount[strFile];
}
RandAddSeed();
}
@ -376,11 +378,11 @@ bool CTxDB::LoadBlockIndex() @@ -376,11 +378,11 @@ bool CTxDB::LoadBlockIndex()
{
if (pindexGenesisBlock == NULL)
return true;
return error("CTxDB::LoadBlockIndex() : hashBestChain not found\n");
return error("CTxDB::LoadBlockIndex() : hashBestChain not found");
}
if (!mapBlockIndex.count(hashBestChain))
return error("CTxDB::LoadBlockIndex() : blockindex for hashBestChain not found\n");
return error("CTxDB::LoadBlockIndex() : blockindex for hashBestChain not found");
pindexBest = mapBlockIndex[hashBestChain];
nBestHeight = pindexBest->nHeight;
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight);
@ -500,16 +502,15 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews) @@ -500,16 +502,15 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews)
CWalletDB::~CWalletDB()
{
// Flush whenever all handles to wallet.dat are closed
Close();
CRITICAL_BLOCK(cs_db)
{
Close(); // close includes a txn_checkpoint
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++);
}
@ -600,6 +601,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet) @@ -600,6 +601,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
if (strKey == "fMinimizeOnClose") ssValue >> fMinimizeOnClose;
if (strKey == "fUseProxy") ssValue >> fUseProxy;
if (strKey == "addrProxy") ssValue >> addrProxy;
}
}
}
@ -610,6 +614,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet) @@ -610,6 +614,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
printf("fMinimizeToTray = %d\n", fMinimizeToTray);
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
printf("fUseProxy = %d\n", fUseProxy);
printf("addrProxy = %s\n", addrProxy.ToString().c_str());
// 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.
@ -639,7 +646,7 @@ bool LoadWallet(bool& fFirstRunRet) @@ -639,7 +646,7 @@ bool LoadWallet(bool& fFirstRunRet)
else
{
// Create new keyUser and set as default key
RandAddSeed(true);
RandAddSeedPerfmon();
keyUser.MakeNewKey();
if (!AddKey(keyUser))
return false;

2
headers.h

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#ifdef _MSC_VER
#pragma warning(disable:4786)
#pragma warning(disable:4804)
#pragma warning(disable:4805)
#pragma warning(disable:4717)
#endif
#ifdef _WIN32_WINNT
@ -62,6 +63,7 @@ using namespace boost; @@ -62,6 +63,7 @@ using namespace boost;
#include "strlcpy.h"
#include "serialize.h"
#include "uint256.h"
#include "util.h"

10
irc.cpp

@ -163,6 +163,9 @@ void ThreadIRCSeed(void* parg) @@ -163,6 +163,9 @@ void ThreadIRCSeed(void* parg)
int nErrorWait = 10;
int nRetryWait = 10;
if (fUseProxy && addrProxy.port == htons(9050))
return;
while (!fShutdown)
{
CAddress addrConnect("216.155.130.130:6667");
@ -191,9 +194,10 @@ void ThreadIRCSeed(void* parg) @@ -191,9 +194,10 @@ void ThreadIRCSeed(void* parg)
return;
}
string strMyName = EncodeAddress(addrLocalHost);
if (!addrLocalHost.IsRoutable())
string strMyName;
if (addrLocalHost.IsRoutable() && !fUseProxy)
strMyName = EncodeAddress(addrLocalHost);
else
strMyName = strprintf("x%u", GetRand(1000000000));

2
key.h

@ -35,7 +35,7 @@ public: @@ -35,7 +35,7 @@ public:
};
// secure_allocator is defined is serialize.h
// secure_allocator is defined in serialize.h
typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;

71
main.cpp

@ -415,6 +415,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -415,6 +415,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
if (!CheckTransaction())
return error("AcceptTransaction() : CheckTransaction failed");
// To help v0.1.5 clients who would see it as negative number. please delete this later.
if (nLockTime > INT_MAX)
return error("AcceptTransaction() : not accepting nLockTime beyond 2038");
// Do we already have it?
uint256 hash = GetHash();
CRITICAL_BLOCK(cs_mapTransactions)
@ -1214,6 +1218,12 @@ bool CBlock::AcceptBlock() @@ -1214,6 +1218,12 @@ bool CBlock::AcceptBlock()
if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
// Check that all transactions are finalized (starting around 30 Nov 2009)
if (nBestHeight > 31000) // 25620 + 5320
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))
return error("AcceptBlock() : incorrect proof of work");
@ -1649,7 +1659,7 @@ bool ProcessMessages(CNode* pfrom) @@ -1649,7 +1659,7 @@ bool ProcessMessages(CNode* pfrom)
CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty())
return true;
printf("ProcessMessages(%d bytes)\n", vRecv.size());
//printf("ProcessMessages(%d bytes)\n", vRecv.size());
//
// Message format
@ -1692,7 +1702,7 @@ bool ProcessMessages(CNode* pfrom) @@ -1692,7 +1702,7 @@ bool ProcessMessages(CNode* pfrom)
{
// Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error
printf("MESSAGE-BREAK\n");
//printf("message-break\n");
vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100);
break;
@ -1711,7 +1721,20 @@ bool ProcessMessages(CNode* pfrom) @@ -1711,7 +1721,20 @@ bool ProcessMessages(CNode* pfrom)
fRet = ProcessMessage(pfrom, strCommand, vMsg);
CheckForShutdown(2);
}
CATCH_PRINT_EXCEPTION("ProcessMessage()")
catch (std::ios_base::failure& e) {
if (strstr(e.what(), "CDataStream::read() : end of data"))
{
// Allow exceptions from underlength message on vRecv
LogException(&e, "ProcessMessage()");
}
else
PrintException(&e, "ProcessMessage()");
} catch (std::exception& e) {
PrintException(&e, "ProcessMessage()");
} catch (...) {
PrintException(NULL, "ProcessMessage()");
}
if (!fRet)
printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize);
}
@ -1726,7 +1749,8 @@ bool ProcessMessages(CNode* pfrom) @@ -1726,7 +1749,8 @@ 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)\n", strCommand.c_str(), vRecv.size());
RandAddSeedPerfmon();
printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());
if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
{
printf("dropmessages DROPPING RECV MESSAGE\n");
@ -1735,18 +1759,32 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1735,18 +1759,32 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (strCommand == "version")
{
// Can only do this once
// Each connection can only send one version message
if (pfrom->nVersion != 0)
return false;
int64 nTime;
CAddress addrMe;
CAddress addrFrom;
uint64 nNonce = 1;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> addrFrom >> nNonce;
if (pfrom->nVersion == 0)
return false;
// Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce)
{
pfrom->fDisconnect = true;
pfrom->vRecv.clear();
pfrom->vSend.clear();
return true;
}
pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
@ -1767,6 +1805,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1767,6 +1805,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
}
pfrom->fSuccessfullyConnected = true;
printf("version message: version %d\n", pfrom->nVersion);
}
@ -1800,16 +1840,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1800,16 +1840,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (fShutdown)
return true;
AddAddress(addrdb, addr);
if (addr.IsRoutable() && addr.ip != addrLocalHost.ip)
pfrom->AddAddressKnown(addr);
if (!pfrom->fGetAddr && addr.IsRoutable())
{
// Put on lists to send to other nodes
pfrom->setAddrKnown.insert(addr);
CRITICAL_BLOCK(cs_vNodes)
foreach(CNode* pnode, vNodes)
if (!pnode->setAddrKnown.count(addr))
pnode->vAddrToSend.push_back(addr);
pnode->PushAddress(addr);
}
}
pfrom->fGetAddr = false;
}
@ -2009,7 +2049,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2009,7 +2049,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return true;
const CAddress& addr = item.second;
if (addr.nTime > nSince)
pfrom->vAddrToSend.push_back(addr);
pfrom->PushAddress(addr);
}
}
}
@ -2108,8 +2148,11 @@ bool SendMessages(CNode* pto) @@ -2108,8 +2148,11 @@ bool SendMessages(CNode* pto)
vector<CAddress> vAddrToSend;
vAddrToSend.reserve(pto->vAddrToSend.size());
foreach(const CAddress& addr, pto->vAddrToSend)
if (!pto->setAddrKnown.count(addr))
{
// returns true if wasn't already contained in the set
if (pto->setAddrKnown.insert(addr).second)
vAddrToSend.push_back(addr);
}
pto->vAddrToSend.clear();
if (!vAddrToSend.empty())
pto->PushMessage("addr", vAddrToSend);
@ -2193,7 +2236,7 @@ void GenerateBitcoins(bool fGenerate) @@ -2193,7 +2236,7 @@ void GenerateBitcoins(bool fGenerate)
if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors;
int nAddThreads = nProcessors - vnThreadsRunning[3];
printf("starting %d bitcoinminer threads\n", nAddThreads);
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");
@ -2207,7 +2250,7 @@ void ThreadBitcoinMiner(void* parg) @@ -2207,7 +2250,7 @@ void ThreadBitcoinMiner(void* parg)
try
{
bool fRet = BitcoinMiner();
printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
printf("BitcoinMiner returned %s\n", fRet ? "true" : "false");
vnThreadsRunning[3]--;
}
catch (std::exception& e) {
@ -2737,7 +2780,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) @@ -2737,7 +2780,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
else
strError = "Error: Transaction creation failed ";
wxMessageBox(strError, "Sending...");
return error("SendMoney() : %s\n", strError.c_str());
return error("SendMoney() : %s", strError.c_str());
}
if (!CommitTransactionSpent(wtxNew, key))
{

16
main.h

@ -366,7 +366,7 @@ public: @@ -366,7 +366,7 @@ public:
int nVersion;
vector<CTxIn> vin;
vector<CTxOut> vout;
int nLockTime;
unsigned int nLockTime;
CTransaction()
@ -401,9 +401,15 @@ public: @@ -401,9 +401,15 @@ public:
return SerializeHash(*this);
}
bool IsFinal() const
bool IsFinal(int64 nBlockTime=0) const
{
if (nLockTime == 0 || nLockTime < nBestHeight)
// Time based nLockTime implemented in 0.1.6,
// do not use time based until most 0.1.5 nodes have upgraded.
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
if (nLockTime == 0)
return true;
if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime))
return true;
foreach(const CTxIn& txin, vin)
if (!txin.IsFinal())
@ -686,8 +692,9 @@ public: @@ -686,8 +692,9 @@ public:
char fSpent;
//// probably need to sign the order info so know it came from payer
// memory only
// memory only UI hints
mutable unsigned int nTimeDisplayed;
mutable int nLinesDisplayed;
CWalletTx()
@ -712,6 +719,7 @@ public: @@ -712,6 +719,7 @@ public:
fFromMe = false;
fSpent = false;
nTimeDisplayed = 0;
nLinesDisplayed = 0;
}
IMPLEMENT_SERIALIZE

4
makefile

@ -17,8 +17,8 @@ endif @@ -17,8 +17,8 @@ endif
INCLUDEPATHS=-I"/boost" -I"/DB/build_unix" -I"/OpenSSL/include" -I"/wxWidgets/lib/vc_lib/mswd" -I"/wxWidgets/include"
LIBPATHS=-L"/DB/build_unix" -L"/OpenSSL/out" -L"/wxWidgets/lib/gcc_lib"
INCLUDEPATHS=-I"/boost" -I"/db/build_unix" -I"/openssl/include" -I"/wxwidgets/lib/vc_lib/mswd" -I"/wxwidgets/include"
LIBPATHS=-L"/db/build_unix" -L"/openssl/out" -L"/wxwidgets/lib/gcc_lib"
LIBS= \
-l db_cxx \
-l eay32 \

173
net.cpp

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
void ThreadMessageHandler2(void* parg);
void ThreadSocketHandler2(void* parg);
void ThreadOpenConnections2(void* parg);
bool OpenNetworkConnection(const CAddress& addrConnect);
@ -22,8 +23,10 @@ uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); @@ -22,8 +23,10 @@ uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
CNode* pnodeLocalHost = &nodeLocalHost;
uint64 nLocalHostNonce = 0;
bool fShutdown = false;
array<int, 10> vnThreadsRunning;
SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
@ -34,9 +37,11 @@ deque<pair<int64, CInv> > vRelayExpiration; @@ -34,9 +37,11 @@ deque<pair<int64, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
map<CInv, int64> mapAlreadyAskedFor;
// Settings
int fUseProxy = false;
CAddress addrProxy("127.0.0.1:9050");
CAddress addrProxy;
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
{
@ -47,7 +52,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) @@ -47,7 +52,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
return false;
bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
bool fProxy = (addrProxy.ip && fRoutable);
bool fProxy = (fUseProxy && fRoutable);
struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
@ -69,18 +74,18 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) @@ -69,18 +74,18 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
if (ret != nSize)
{
closesocket(hSocket);
return error("Error sending to proxy\n");
return error("Error sending to proxy");
}
char pchRet[8];
if (recv(hSocket, pchRet, 8, 0) != 8)
{
closesocket(hSocket);
return error("Error reading proxy response\n");
return error("Error reading proxy response");
}
if (pchRet[1] != 0x5a)
{
closesocket(hSocket);
return error("Proxy returned error %d\n", pchRet[1]);
return error("Proxy returned error %d", pchRet[1]);
}
printf("Proxy connection established %s\n", addrConnect.ToStringLog().c_str());
}
@ -95,7 +100,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha @@ -95,7 +100,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
{
SOCKET hSocket;
if (!ConnectSocket(addrConnect, hSocket))
return error("GetMyExternalIP() : connection to %s failed\n", addrConnect.ToString().c_str());
return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
send(hSocket, pszGet, strlen(pszGet), 0);
@ -131,7 +136,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha @@ -131,7 +136,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
}
}
closesocket(hSocket);
return error("GetMyExternalIP() : connection closed\n");
return error("GetMyExternalIP() : connection closed");
}
@ -141,6 +146,9 @@ bool GetMyExternalIP(unsigned int& ipRet) @@ -141,6 +146,9 @@ bool GetMyExternalIP(unsigned int& ipRet)
char* pszGet;
char* pszKeyword;
if (fUseProxy)
return false;
for (int nLookup = 0; nLookup <= 1; nLookup++)
for (int nHost = 1; nHost <= 2; nHost++)
{
@ -416,14 +424,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) @@ -416,14 +424,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
}
}
void CNode::Disconnect()
void CNode::DoDisconnect()
{
printf("disconnecting node %s\n", addr.ToStringLog().c_str());
closesocket(hSocket);
// If outbound and never got version message, mark address as failed
if (!fInbound && nVersion == 0)
if (!fInbound && !fSuccessfullyConnected)
CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addr.GetKey()].nLastFailed = GetTime();
@ -458,18 +466,18 @@ void ThreadSocketHandler(void* parg) @@ -458,18 +466,18 @@ void ThreadSocketHandler(void* parg)
loop
{
vnThreadsRunning[0] = true;
vnThreadsRunning[0]++;
CheckForShutdown(0);
try
{
ThreadSocketHandler2(parg);
vnThreadsRunning[0] = false;
vnThreadsRunning[0]--;
}
catch (std::exception& e) {
vnThreadsRunning[0] = false;
vnThreadsRunning[0]--;
PrintException(&e, "ThreadSocketHandler()");
} catch (...) {
vnThreadsRunning[0] = false;
vnThreadsRunning[0]--;
PrintException(NULL, "ThreadSocketHandler()");
}
Sleep(5000);
@ -479,7 +487,6 @@ void ThreadSocketHandler(void* parg) @@ -479,7 +487,6 @@ void ThreadSocketHandler(void* parg)
void ThreadSocketHandler2(void* parg)
{
printf("ThreadSocketHandler started\n");
SOCKET hListenSocket = *(SOCKET*)parg;
list<CNode*> vNodesDisconnected;
int nPrevNodeCount = 0;
@ -498,7 +505,7 @@ void ThreadSocketHandler2(void* parg) @@ -498,7 +505,7 @@ void ThreadSocketHandler2(void* parg)
{
// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
pnode->Disconnect();
pnode->DoDisconnect();
// hold in disconnected pool until all refs are released
pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 5 * 60);
@ -562,9 +569,9 @@ void ThreadSocketHandler2(void* parg) @@ -562,9 +569,9 @@ void ThreadSocketHandler2(void* parg)
}
}
vnThreadsRunning[0] = false;
vnThreadsRunning[0]--;
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
vnThreadsRunning[0] = true;
vnThreadsRunning[0]++;
CheckForShutdown(0);
if (nSelect == SOCKET_ERROR)
{
@ -577,7 +584,6 @@ void ThreadSocketHandler2(void* parg) @@ -577,7 +584,6 @@ void ThreadSocketHandler2(void* parg)
}
Sleep(timeout.tv_usec/1000);
}
RandAddSeed();
//// debug print
//foreach(CNode* pnode, vNodes)
@ -711,18 +717,18 @@ void ThreadOpenConnections(void* parg) @@ -711,18 +717,18 @@ void ThreadOpenConnections(void* parg)
loop
{
vnThreadsRunning[1] = true;
vnThreadsRunning[1]++;
CheckForShutdown(1);
try
{
ThreadOpenConnections2(parg);
vnThreadsRunning[1] = false;
vnThreadsRunning[1]--;
}
catch (std::exception& e) {
vnThreadsRunning[1] = false;
vnThreadsRunning[1]--;
PrintException(&e, "ThreadOpenConnections()");
} catch (...) {
vnThreadsRunning[1] = false;
vnThreadsRunning[1]--;
PrintException(NULL, "ThreadOpenConnections()");
}
Sleep(5000);
@ -733,6 +739,13 @@ void ThreadOpenConnections2(void* parg) @@ -733,6 +739,13 @@ void ThreadOpenConnections2(void* parg)
{
printf("ThreadOpenConnections started\n");
// Connect to one specified address
while (mapArgs.count("/connect"))
{
OpenNetworkConnection(CAddress(mapArgs["/connect"].c_str()));
Sleep(10000);
}
// Initiate network connections
int nTry = 0;
bool fIRCOnly = false;
@ -740,14 +753,14 @@ void ThreadOpenConnections2(void* parg) @@ -740,14 +753,14 @@ void ThreadOpenConnections2(void* parg)
loop
{
// Wait
vnThreadsRunning[1] = false;
vnThreadsRunning[1]--;
Sleep(500);
while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
{
CheckForShutdown(1);
Sleep(2000);
}
vnThreadsRunning[1] = true;
vnThreadsRunning[1]++;
CheckForShutdown(1);
@ -835,43 +848,48 @@ void ThreadOpenConnections2(void* parg) @@ -835,43 +848,48 @@ void ThreadOpenConnections2(void* parg)
// Once we've chosen an IP, we'll try every given port before moving on
foreach(const CAddress& addrConnect, (*mi).second)
{
//
// Initiate outbound network connection
//
CheckForShutdown(1);
if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
continue;
if (OpenNetworkConnection(addrConnect))
break;
}
}
vnThreadsRunning[1] = false;
CNode* pnode = ConnectNode(addrConnect);
vnThreadsRunning[1] = true;
CheckForShutdown(1);
if (!pnode)
continue;
pnode->fNetworkNode = true;
bool OpenNetworkConnection(const CAddress& addrConnect)
{
//
// Initiate outbound network connection
//
CheckForShutdown(1);
if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
return false;
if (addrLocalHost.IsRoutable())
{
// Advertise our address
vector<CAddress> vAddrToSend;
vAddrToSend.push_back(addrLocalHost);
pnode->PushMessage("addr", vAddrToSend);
}
vnThreadsRunning[1]--;
CNode* pnode = ConnectNode(addrConnect);
vnThreadsRunning[1]++;
CheckForShutdown(1);
if (!pnode)
return false;
pnode->fNetworkNode = true;
// Get as many addresses as we can
pnode->PushMessage("getaddr");
if (addrLocalHost.IsRoutable() && !fUseProxy)
{
// Advertise our address
vector<CAddress> vAddrToSend;
vAddrToSend.push_back(addrLocalHost);
pnode->PushMessage("addr", vAddrToSend);
}
////// should the one on the receiving end do this too?
// Subscribe our local subscription list
const unsigned int nHops = 0;
for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
if (pnodeLocalHost->vfSubscribe[nChannel])
pnode->PushMessage("subscribe", nChannel, nHops);
// Get as many addresses as we can
pnode->PushMessage("getaddr");
pnode->fGetAddr = true; // don't relay the results of the getaddr
break;
}
}
////// should the one on the receiving end do this too?
// Subscribe our local subscription list
const unsigned int nHops = 0;
for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
if (pnodeLocalHost->vfSubscribe[nChannel])
pnode->PushMessage("subscribe", nChannel, nHops);
return true;
}
@ -887,18 +905,18 @@ void ThreadMessageHandler(void* parg) @@ -887,18 +905,18 @@ void ThreadMessageHandler(void* parg)
loop
{
vnThreadsRunning[2] = true;
vnThreadsRunning[2]++;
CheckForShutdown(2);
try
{
ThreadMessageHandler2(parg);
vnThreadsRunning[2] = false;
vnThreadsRunning[2]--;
}
catch (std::exception& e) {
vnThreadsRunning[2] = false;
vnThreadsRunning[2]--;
PrintException(&e, "ThreadMessageHandler()");
} catch (...) {
vnThreadsRunning[2] = false;
vnThreadsRunning[2]--;
PrintException(NULL, "ThreadMessageHandler()");
}
Sleep(5000);
@ -931,9 +949,9 @@ void ThreadMessageHandler2(void* parg) @@ -931,9 +949,9 @@ void ThreadMessageHandler2(void* parg)
}
// Wait and allow messages to bunch up
vnThreadsRunning[2] = false;
vnThreadsRunning[2]--;
Sleep(100);
vnThreadsRunning[2] = true;
vnThreadsRunning[2]++;
CheckForShutdown(2);
}
}
@ -982,7 +1000,7 @@ bool StartNode(string& strError) @@ -982,7 +1000,7 @@ bool StartNode(string& strError)
printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
// Create socket for listening for incoming connections
SOCKET hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (hListenSocket == INVALID_SOCKET)
{
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
@ -1024,13 +1042,21 @@ bool StartNode(string& strError) @@ -1024,13 +1042,21 @@ bool StartNode(string& strError)
}
// Get our external IP address for incoming connections
if (addrIncoming.ip)
addrLocalHost.ip = addrIncoming.ip;
if (GetMyExternalIP(addrLocalHost.ip))
if (fUseProxy)
{
addrIncoming = addrLocalHost;
CWalletDB().WriteSetting("addrIncoming", addrIncoming);
// Proxies can't take incoming connections
addrLocalHost.ip = CAddress("0.0.0.0").ip;
}
else
{
if (addrIncoming.ip)
addrLocalHost.ip = addrIncoming.ip;
if (GetMyExternalIP(addrLocalHost.ip))
{
addrIncoming = addrLocalHost;
CWalletDB().WriteSetting("addrIncoming", addrIncoming);
}
}
// Get addresses from IRC and advertise ours
@ -1040,7 +1066,7 @@ bool StartNode(string& strError) @@ -1040,7 +1066,7 @@ bool StartNode(string& strError)
//
// Start threads
//
if (_beginthread(ThreadSocketHandler, 0, new SOCKET(hListenSocket)) == -1)
if (_beginthread(ThreadSocketHandler, 0, NULL) == -1)
{
strError = "Error: _beginthread(ThreadSocketHandler) failed";
printf("%s\n", strError.c_str());
@ -1094,10 +1120,15 @@ void CheckForShutdown(int n) @@ -1094,10 +1120,15 @@ void CheckForShutdown(int n)
if (fShutdown)
{
if (n != -1)
vnThreadsRunning[n] = false;
if (--vnThreadsRunning[n] < 0)
vnThreadsRunning[n] = 0;
if (n == 0)
{
foreach(CNode* pnode, vNodes)
closesocket(pnode->hSocket);
closesocket(hListenSocket);
}
printf("Thread %d exiting\n", n);
_endthread();
}
}

131
net.h

@ -174,7 +174,7 @@ public: @@ -174,7 +174,7 @@ public:
{
nServices = nServicesIn;
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = 0;
ip = INADDR_NONE;
port = DEFAULT_PORT;
nTime = GetAdjustedTime();
nLastFailed = 0;
@ -183,7 +183,7 @@ public: @@ -183,7 +183,7 @@ public:
if (strlen(pszIn) > ARRAYLEN(psz)-1)
return;
strcpy(psz, pszIn);
unsigned int a, b, c, d, e;
unsigned int a=0, b=0, c=0, d=0, e=0;
if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4)
return;
char* pszPort = strchr(psz, ':');
@ -191,6 +191,10 @@ public: @@ -191,6 +191,10 @@ public:
{
*pszPort++ = '\0';
port = htons(atoi(pszPort));
if (atoi(pszPort) > USHRT_MAX)
port = htons(USHRT_MAX);
if (atoi(pszPort) < 0)
port = htons(0);
}
ip = inet_addr(psz);
}
@ -215,6 +219,11 @@ public: @@ -215,6 +219,11 @@ public:
a.port == b.port);
}
friend inline bool operator!=(const CAddress& a, const CAddress& b)
{
return (!(a == b));
}
friend inline bool operator<(const CAddress& a, const CAddress& b)
{
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
@ -277,6 +286,11 @@ public: @@ -277,6 +286,11 @@ public:
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
}
string ToStringPort() const
{
return strprintf("%u", ntohs(port));
}
string ToStringLog() const
{
return "";
@ -416,6 +430,7 @@ extern bool fClient; @@ -416,6 +430,7 @@ extern bool fClient;
extern uint64 nLocalServices;
extern CAddress addrLocalHost;
extern CNode* pnodeLocalHost;
extern uint64 nLocalHostNonce;
extern bool fShutdown;
extern array<int, 10> vnThreadsRunning;
extern vector<CNode*> vNodes;
@ -426,6 +441,9 @@ extern map<CInv, CDataStream> mapRelay; @@ -426,6 +441,9 @@ extern map<CInv, CDataStream> mapRelay;
extern deque<pair<int64, CInv> > vRelayExpiration;
extern CCriticalSection cs_mapRelay;
extern map<CInv, int64> mapAlreadyAskedFor;
// Settings
extern int fUseProxy;
extern CAddress addrProxy;
@ -448,6 +466,7 @@ public: @@ -448,6 +466,7 @@ public:
bool fClient;
bool fInbound;
bool fNetworkNode;
bool fSuccessfullyConnected;
bool fDisconnect;
protected:
int nRefCount;
@ -459,6 +478,7 @@ public: @@ -459,6 +478,7 @@ public:
// flood
vector<CAddress> vAddrToSend;
set<CAddress> setAddrKnown;
bool fGetAddr;
// inventory based relay
set<CInv> setInventoryKnown;
@ -483,15 +503,20 @@ public: @@ -483,15 +503,20 @@ public:
fClient = false; // set by version message
fInbound = fInboundIn;
fNetworkNode = false;
fSuccessfullyConnected = false;
fDisconnect = false;
nRefCount = 0;
nReleaseTime = 0;
fGetAddr = false;
vfSubscribe.assign(256, false);
// Push a version message
/// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
PushMessage("version", VERSION, nLocalServices, nTime, addr);
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);
}
~CNode()
@ -531,6 +556,21 @@ public: @@ -531,6 +556,21 @@ public:
void AddAddressKnown(const CAddress& addr)
{
setAddrKnown.insert(addr);
}
void PushAddress(const CAddress& addr)
{
// Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added
// after addresses were pushed.
if (!setAddrKnown.count(addr))
vAddrToSend.push_back(addr);
}
void AddInventoryKnown(const CInv& inv)
{
CRITICAL_BLOCK(cs_inventory)
@ -562,7 +602,6 @@ public: @@ -562,7 +602,6 @@ public:
}
void BeginMessage(const char* pszCommand)
{
EnterCriticalSection(&cs_vSend);
@ -570,7 +609,7 @@ public: @@ -570,7 +609,7 @@ public:
AbortMessage();
nPushPos = vSend.size();
vSend << CMessageHeader(pszCommand, 0);
printf("sending: %-12s ", pszCommand);
printf("sending: %s ", pszCommand);
}
void AbortMessage()
@ -706,6 +745,86 @@ public: @@ -706,6 +745,86 @@ public:
}
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
{
try
{
BeginMessage(pszCommand);
vSend << a1 << a2 << a3 << a4 << a5;
EndMessage();
}
catch (...)
{
AbortMessage();
throw;
}
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
{
try
{
BeginMessage(pszCommand);
vSend << a1 << a2 << a3 << a4 << a5 << a6;
EndMessage();
}
catch (...)
{
AbortMessage();
throw;
}
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7)
{
try
{
BeginMessage(pszCommand);
vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
EndMessage();
}
catch (...)
{
AbortMessage();
throw;
}
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8)
{
try
{
BeginMessage(pszCommand);
vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
EndMessage();
}
catch (...)
{
AbortMessage();
throw;
}
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9)
{
try
{
BeginMessage(pszCommand);
vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
EndMessage();
}
catch (...)
{
AbortMessage();
throw;
}
}
void PushRequest(const char* pszCommand,
void (*fn)(void*, CDataStream&), void* param1)
@ -750,7 +869,7 @@ public: @@ -750,7 +869,7 @@ public:
bool IsSubscribed(unsigned int nChannel);
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
void CancelSubscribe(unsigned int nChannel);
void Disconnect();
void DoDisconnect();
};

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;

84
strlcpy.h

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
inline size_t strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0)
{
while (--n != 0)
{
if ((*d++ = *s++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0)
{
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
inline size_t strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0')
{
if (n != 1)
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}

223
ui.cpp

@ -497,7 +497,7 @@ string SingleLine(const string& strIn) @@ -497,7 +497,7 @@ string SingleLine(const string& strIn)
return strOut;
}
void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
{
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
int64 nCredit = wtx.GetCredit();
@ -506,14 +506,11 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -506,14 +506,11 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
uint256 hash = wtx.GetHash();
string strStatus = FormatTxStatus(wtx);
map<string, string> mapValue = wtx.mapValue;
wtx.nLinesDisplayed = 1;
// 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.
//
@ -527,10 +524,13 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -527,10 +524,13 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
//
if (wtx.GetDepthInMainChain() < 2)
{
// In case it was previously displayed
DeleteLine(hash);
return;
wtx.nLinesDisplayed = 0;
return false;
}
// View->Show Generated
if (!fShowGenerated)
return false;
}
// Find the block the tx is in
@ -644,6 +644,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -644,6 +644,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
// Debit
//
int64 nTxFee = nDebit - wtx.GetValueOut();
wtx.nLinesDisplayed = 0;
for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
{
const CTxOut& txout = wtx.vout[nOut];
@ -685,6 +686,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -685,6 +686,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
SingleLine(strDescription),
FormatMoney(-nValue, true),
"");
wtx.nLinesDisplayed++;
}
}
else
@ -706,12 +708,14 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -706,12 +708,14 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
"");
}
}
return true;
}
void CMainFrame::RefreshStatus()
{
static int nLastTop;
int nTop = m_listCtrl->GetTopItem();
int nTop = max((int)m_listCtrl->GetTopItem(), 0);
if (nTop == nLastTop && pindexBestLast == pindexBest)
return;
@ -729,7 +733,7 @@ void CMainFrame::RefreshStatus() @@ -729,7 +733,7 @@ void CMainFrame::RefreshStatus()
nLastTop = nTop;
pindexBestLast = pindexBest;
for (int nIndex = nStart; nIndex < nEnd; nIndex++)
for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
{
uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
@ -738,9 +742,12 @@ void CMainFrame::RefreshStatus() @@ -738,9 +742,12 @@ void CMainFrame::RefreshStatus()
printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n");
continue;
}
const CWalletTx& wtx = (*mi).second;
CWalletTx& wtx = (*mi).second;
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
InsertTransaction(wtx, false, nIndex);
{
if (!InsertTransaction(wtx, false, nIndex))
m_listCtrl->DeleteItem(nIndex--);
}
else
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
}
@ -801,6 +808,9 @@ void CMainFrame::OnIdle(wxIdleEvent& event) @@ -801,6 +808,9 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
}
printf("RefreshListCtrl done\n");
// Update transaction total display
MainFrameRepaint();
}
else
{