aboutsummaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-11-13 01:23:08 +0000
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-11-13 01:23:08 +0000
commit31e6ea7f5d5b3d73f4084261465142c9fe0fb894 (patch)
tree7427ce9b17468ed4a9dec82b380c2dd40a5332ca /main.cpp
parente9c2b5c84d7bbb7f173cbe6035f6299248e14769 (diff)
monitor ThreadSocketHandler and terminate and restart if hung, convert _beginthread to CreateThread wrapper, disconnect inactive connections, ping, break up long messages to speed up initial download, better priorities for initiating connections, track how many nodes have requested our blocks and transactions, status #/offline and warning message on unsent blocks, minimize on close as separate option -- linux-test5
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp144
1 files changed, 120 insertions, 24 deletions
diff --git a/main.cpp b/main.cpp
index b957027f07..13a9f9b72a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -42,6 +42,9 @@ map<uint160, vector<unsigned char> > mapPubKeys;
CCriticalSection cs_mapKeys;
CKey keyUser;
+map<uint256, int> mapRequestCount;
+CCriticalSection cs_mapRequestCount;
+
// Settings
int fGenerateBitcoins = false;
int64 nTransactionFee = 0;
@@ -274,7 +277,44 @@ int64 CWalletTx::GetTxTime() const
return nTimeReceived;
}
+int CWalletTx::GetRequestCount() const
+{
+ // Returns -1 if it wasn't being tracked
+ int nRequests = -1;
+ CRITICAL_BLOCK(cs_mapRequestCount)
+ {
+ if (IsCoinBase())
+ {
+ // Generated block
+ if (hashBlock != 0)
+ {
+ map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
+ if (mi != mapRequestCount.end())
+ nRequests = (*mi).second;
+ }
+ }
+ else
+ {
+ // Did anyone request this transaction?
+ map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());
+ if (mi != mapRequestCount.end())
+ {
+ nRequests = (*mi).second;
+ // How about the block it's in?
+ if (nRequests == 0 && hashBlock != 0)
+ {
+ map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
+ if (mi != mapRequestCount.end())
+ nRequests = (*mi).second;
+ else
+ nRequests = 1; // If it's in someone else's block it must have got out
+ }
+ }
+ }
+ }
+ return nRequests;
+}
@@ -295,7 +335,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
CTxIndex txindex;
if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
return 0;
- if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, true))
+ if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))
return 0;
pblock = &blockTmp;
}
@@ -1003,7 +1043,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
foreach(CBlockIndex* pindex, vDisconnect)
{
CBlock block;
- if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
+ if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
return error("Reorganize() : ReadFromDisk for disconnect failed");
if (!block.DisconnectBlock(txdb, pindex))
return error("Reorganize() : DisconnectBlock failed");
@@ -1020,7 +1060,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
{
CBlockIndex* pindex = vConnect[i];
CBlock block;
- if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
+ if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
return error("Reorganize() : ReadFromDisk for connect failed");
if (!block.ConnectBlock(txdb, pindex))
{
@@ -1380,7 +1420,7 @@ bool CheckDiskSpace(int64 nAdditionalBytes)
{
fShutdown = true;
ThreadSafeMessageBox("Warning: Your disk space is low ", "Bitcoin", wxOK | wxICON_EXCLAMATION);
- _beginthread(Shutdown, 0, NULL);
+ CreateThread(Shutdown, NULL);
return false;
}
return true;
@@ -1547,7 +1587,7 @@ void PrintBlockTree()
// print item
CBlock block;
- block.ReadFromDisk(pindex, true);
+ block.ReadFromDisk(pindex);
printf("%d (%u,%u) %s %s tx %d",
pindex->nHeight,
pindex->nFile,
@@ -1623,7 +1663,8 @@ bool ProcessMessages(CNode* pfrom)
CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty())
return true;
- //printf("ProcessMessages(%d bytes)\n", vRecv.size());
+ //if (fDebug)
+ // printf("ProcessMessages(%d bytes)\n", vRecv.size());
//
// Message format
@@ -1666,7 +1707,8 @@ 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");
+ //if (fDebug)
+ // printf("message-break\n");
vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100);
break;
@@ -1718,6 +1760,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
static map<unsigned int, vector<unsigned char> > mapReuseKey;
RandAddSeedPerfmon();
+ if (fDebug)
+ printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
@@ -1739,18 +1783,19 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CAddress addrMe;
CAddress addrFrom;
uint64 nNonce = 1;
+ string strSubVer;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> addrFrom >> nNonce;
+ if (pfrom->nVersion >= 106 && !vRecv.empty())
+ vRecv >> strSubVer;
if (pfrom->nVersion == 0)
return false;
// Disconnect if we connected to ourself
- if (nNonce == nLocalHostNonce)
+ if (nNonce == nLocalHostNonce && nNonce > 1)
{
pfrom->fDisconnect = true;
- pfrom->vRecv.clear();
- pfrom->vSend.clear();
return true;
}
@@ -1776,10 +1821,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true;
- // Update the last seen time
- if (pfrom->fNetworkNode)
- AddressCurrentlyConnected(pfrom->addr);
-
printf("version message: version %d\n", pfrom->nVersion);
}
@@ -1824,10 +1865,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vector<CInv> vInv;
vRecv >> vInv;
- // Update the last seen time for this node's address
- if (pfrom->fNetworkNode)
- AddressCurrentlyConnected(pfrom->addr);
-
CTxDB txdb("r");
foreach(const CInv& inv, vInv)
{
@@ -1842,6 +1879,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->AskFor(inv);
else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
+
+ // Track requests for our stuff
+ CRITICAL_BLOCK(cs_mapRequestCount)
+ {
+ map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
+ if (mi != mapRequestCount.end())
+ (*mi).second++;
+ }
}
}
@@ -1879,6 +1924,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
}
}
+
+ // Track requests for our stuff
+ CRITICAL_BLOCK(cs_mapRequestCount)
+ {
+ map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
+ if (mi != mapRequestCount.end())
+ (*mi).second++;
+ }
}
}
@@ -2086,11 +2139,23 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
+ else if (strCommand == "ping")
+ {
+ }
+
+
else
{
// Ignore unknown commands for extensibility
}
+
+ // Update the last seen time for this node's address
+ if (pfrom->fNetworkNode)
+ if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")
+ AddressCurrentlyConnected(pfrom->addr);
+
+
return true;
}
@@ -2129,6 +2194,10 @@ bool SendMessages(CNode* pto)
}
}
+ // Keep-alive ping
+ if (pto->nLastSend && GetTime() - pto->nLastSend > 12 * 60 && pto->vSend.empty())
+ pto->PushMessage("ping");
+
//
// Message: addr
@@ -2139,7 +2208,14 @@ bool SendMessages(CNode* pto)
{
// returns true if wasn't already contained in the set
if (pto->setAddrKnown.insert(addr).second)
+ {
vAddrToSend.push_back(addr);
+ if (vAddrToSend.size() >= 1000)
+ {
+ pto->PushMessage("addr", vAddrToSend);
+ vAddrToSend.clear();
+ }
+ }
}
pto->vAddrToSend.clear();
if (!vAddrToSend.empty())
@@ -2157,7 +2233,14 @@ bool SendMessages(CNode* pto)
{
// returns true if wasn't already contained in the set
if (pto->setInventoryKnown.insert(inv).second)
+ {
vInventoryToSend.push_back(inv);
+ if (vInventoryToSend.size() >= 1000)
+ {
+ pto->PushMessage("inv", vInventoryToSend);
+ vInventoryToSend.clear();
+ }
+ }
}
pto->vInventoryToSend.clear();
pto->setInventoryKnown2.clear();
@@ -2179,6 +2262,11 @@ bool SendMessages(CNode* pto)
{
printf("sending getdata: %s\n", inv.ToString().c_str());
vAskFor.push_back(inv);
+ if (vAskFor.size() >= 1000)
+ {
+ pto->PushMessage("getdata", vAskFor);
+ vAskFor.clear();
+ }
}
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
@@ -2226,8 +2314,8 @@ void GenerateBitcoins(bool fGenerate)
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");
+ if (!CreateThread(ThreadBitcoinMiner, NULL))
+ printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
}
}
@@ -2304,7 +2392,7 @@ void BitcoinMiner()
CBigNum bnExtraNonce = 0;
while (fGenerateBitcoins)
{
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
+ SetThreadPriority(THREAD_PRIORITY_LOWEST);
Sleep(50);
if (fShutdown)
return;
@@ -2440,7 +2528,7 @@ void BitcoinMiner()
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
pblock->print();
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+ SetThreadPriority(THREAD_PRIORITY_NORMAL);
CRITICAL_BLOCK(cs_main)
{
if (pindexPrev == pindexBest)
@@ -2450,12 +2538,16 @@ void BitcoinMiner()
return;
key.MakeNewKey();
+ // Track how many getdata requests this block gets
+ CRITICAL_BLOCK(cs_mapRequestCount)
+ mapRequestCount[pblock->GetHash()] = 0;
+
// Process this block the same as if we had received it from another node
if (!ProcessBlock(NULL, pblock.release()))
printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
}
}
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
+ SetThreadPriority(THREAD_PRIORITY_LOWEST);
Sleep(500);
break;
@@ -2534,7 +2626,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
setCoinsRet.clear();
// List of values less than target
- int64 nLowestLarger = _I64_MAX;
+ int64 nLowestLarger = INT64_MAX;
CWalletTx* pcoinLowestLarger = NULL;
vector<pair<int64, CWalletTx*> > vValue;
int64 nTotalLower = 0;
@@ -2777,6 +2869,10 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
return error("SendMoney() : Error finalizing transaction");
}
+ // Track how many getdata requests our transaction gets
+ CRITICAL_BLOCK(cs_mapRequestCount)
+ mapRequestCount[wtxNew.GetHash()] = 0;
+
printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());
// Broadcast