diff --git a/cryptopp/secblock.h b/cryptopp/secblock.h index d66470e9..5e388291 100644 --- a/cryptopp/secblock.h +++ b/cryptopp/secblock.h @@ -184,7 +184,8 @@ public: void deallocate(void *p, size_type n) { - assert(false); + //// Bitcoin: can't figure out why this is tripping on a few compiles. + //assert(false); } size_type max_size() const {return 0;} diff --git a/db.cpp b/db.cpp index 56ec9ee6..6b3af257 100644 --- a/db.cpp +++ b/db.cpp @@ -820,10 +820,15 @@ void BackupWallet(const string& strDest) mapFileUseCount.erase(strFile); // Copy wallet.dat + filesystem::path pathSrc(GetDataDir() + "/" + strFile); filesystem::path pathDest(strDest); if (filesystem::is_directory(pathDest)) pathDest = pathDest / strFile; - filesystem::copy_file(filesystem::path(GetDataDir() + "/" + strFile), pathDest, filesystem::copy_option::overwrite_if_exists); +#if BOOST_VERSION >= 104000 + filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); +#else + filesystem::copy_file(pathSrc, pathDest); +#endif printf("copied wallet.dat to %s\n", pathDest.string().c_str()); return; diff --git a/init.cpp b/init.cpp index af8ad753..43a672f5 100644 --- a/init.cpp +++ b/init.cpp @@ -297,7 +297,7 @@ bool AppInit2(int argc, char* argv[]) if (!strErrors.empty()) { - wxMessageBox(strErrors, "Bitcoin"); + wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR); return false; } @@ -374,7 +374,7 @@ bool AppInit2(int argc, char* argv[]) return false; } if (nTransactionFee > 1 * COIN) - wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin"); + wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION); } // diff --git a/irc.cpp b/irc.cpp index daa9a0db..a520173f 100644 --- a/irc.cpp +++ b/irc.cpp @@ -6,6 +6,9 @@ int nGotIRCAddresses = 0; +void ThreadIRCSeed2(void* parg); + + #pragma pack(push, 1) @@ -128,6 +131,7 @@ int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const cha loop { string strLine; + strLine.reserve(10000); if (!RecvLineIRC(hSocket, strLine)) return 0; printf("IRC %s\n", strLine.c_str()); @@ -157,6 +161,21 @@ bool Wait(int nSeconds) void ThreadIRCSeed(void* parg) +{ + IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg)); + try + { + ThreadIRCSeed2(parg); + } + catch (std::exception& e) { + PrintExceptionContinue(&e, "ThreadIRCSeed()"); + } catch (...) { + PrintExceptionContinue(NULL, "ThreadIRCSeed()"); + } + printf("ThreadIRCSeed exiting\n"); +} + +void ThreadIRCSeed2(void* parg) { if (mapArgs.count("-connect")) return; @@ -236,6 +255,7 @@ void ThreadIRCSeed(void* parg) int64 nStart = GetTime(); string strLine; + strLine.reserve(10000); while (!fShutdown && RecvLineIRC(hSocket, strLine)) { if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':') diff --git a/main.cpp b/main.cpp index 76d30373..835b7c7a 100644 --- a/main.cpp +++ b/main.cpp @@ -91,7 +91,7 @@ vector GenerateNewKey() CKey key; key.MakeNewKey(); if (!AddKey(key)) - throw runtime_error("GenerateNewKey() : AddKey failed\n"); + throw runtime_error("GenerateNewKey() : AddKey failed"); return key.GetPubKey(); } @@ -487,21 +487,25 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) -bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs) +bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs) { if (pfMissingInputs) *pfMissingInputs = false; // Coinbase is only valid in a block, not as a loose transaction if (IsCoinBase()) - return error("AcceptTransaction() : coinbase as individual tx"); + return error("AcceptToMemoryPool() : coinbase as individual tx"); if (!CheckTransaction()) - return error("AcceptTransaction() : CheckTransaction failed"); + return error("AcceptToMemoryPool() : CheckTransaction failed"); // To help v0.1.5 clients who would see it as a negative number if ((int64)nLockTime > INT_MAX) - return error("AcceptTransaction() : not accepting nLockTime beyond 2038 yet"); + return error("AcceptToMemoryPool() : not accepting nLockTime beyond 2038 yet"); + + // Rather not work on nonstandard transactions + if (GetSigOpCount() > 2 || ::GetSerializeSize(*this, SER_NETWORK) < 100) + return error("AcceptToMemoryPool() : nonstandard transaction"); // Do we already have it? uint256 hash = GetHash(); @@ -545,7 +549,7 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis { if (pfMissingInputs) *pfMissingInputs = true; - return error("AcceptTransaction() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str()); + return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str()); } // Store transaction in memory @@ -553,10 +557,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis { if (ptxOld) { - printf("AcceptTransaction() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); + printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); ptxOld->RemoveFromMemoryPool(); } - AddToMemoryPool(); + AddToMemoryPoolUnchecked(); } ///// are we sure this is ok when loading transactions or restoring block txes @@ -564,15 +568,15 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis if (ptxOld) EraseFromWallet(ptxOld->GetHash()); - printf("AcceptTransaction(): accepted %s\n", hash.ToString().substr(0,6).c_str()); + printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,6).c_str()); return true; } -bool CTransaction::AddToMemoryPool() +bool CTransaction::AddToMemoryPoolUnchecked() { // Add to memory pool without checking anything. Don't call this directly, - // call AcceptTransaction to properly check the transaction first. + // call AcceptToMemoryPool to properly check the transaction first. CRITICAL_BLOCK(cs_mapTransactions) { uint256 hash = GetHash(); @@ -637,17 +641,17 @@ int CMerkleTx::GetBlocksToMaturity() const } -bool CMerkleTx::AcceptTransaction(CTxDB& txdb, bool fCheckInputs) +bool CMerkleTx::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs) { if (fClient) { if (!IsInMainChain() && !ClientConnectInputs()) return false; - return CTransaction::AcceptTransaction(txdb, false); + return CTransaction::AcceptToMemoryPool(txdb, false); } else { - return CTransaction::AcceptTransaction(txdb, fCheckInputs); + return CTransaction::AcceptToMemoryPool(txdb, fCheckInputs); } } @@ -657,19 +661,19 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs) { CRITICAL_BLOCK(cs_mapTransactions) { + // Add previous supporting transactions first foreach(CMerkleTx& tx, vtxPrev) { if (!tx.IsCoinBase()) { uint256 hash = tx.GetHash(); if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash)) - tx.AcceptTransaction(txdb, fCheckInputs); + tx.AcceptToMemoryPool(txdb, fCheckInputs); } } - if (!IsCoinBase()) - return AcceptTransaction(txdb, fCheckInputs); + return AcceptToMemoryPool(txdb, fCheckInputs); } - return true; + return false; } void ReacceptWalletTransactions() @@ -1046,6 +1050,8 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map& mapTestPoo if (nTxFee < nMinFee) return false; nFees += nTxFee; + if (!MoneyRange(nFees)) + return error("ConnectInputs() : nFees out of range"); } if (fBlock) @@ -1098,6 +1104,9 @@ bool CTransaction::ClientConnectInputs() // txPrev.vout[prevout.n].posNext = posThisTx; nValueIn += txPrev.vout[prevout.n].nValue; + + if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn)) + return error("ClientConnectInputs() : txin values out of range"); } if (GetValueOut() > nValueIn) return false; @@ -1251,7 +1260,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) // Resurrect memory transactions that were in the disconnected branch foreach(CTransaction& tx, vResurrect) - tx.AcceptTransaction(txdb, false); + tx.AcceptToMemoryPool(txdb, false); // Delete redundant memory transactions that are in the connected branch foreach(CTransaction& tx, vDelete) @@ -1365,7 +1374,7 @@ bool CBlock::CheckBlock() const // that can be verified before saving an orphan block. // Size limits - if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE) + if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_NETWORK) > MAX_SIZE) return error("CheckBlock() : size limits failed"); // Check timestamp @@ -1407,6 +1416,15 @@ bool CBlock::AcceptBlock() if (mi == mapBlockIndex.end()) return error("AcceptBlock() : prev block not found"); CBlockIndex* pindexPrev = (*mi).second; + int nHeight = pindexPrev->nHeight+1; + + // Check size + if (nHeight > 79400 && ::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE) + return error("AcceptBlock() : over size limit"); + + // Check that it's not full of nonstandard transactions + if (nHeight > 79400 && GetSigOpCount() > MAX_BLOCK_SIGOPS) + return error("AcceptBlock() : too many nonstandard transactions"); // Check timestamp against prev if (GetBlockTime() <= pindexPrev->GetMedianTimePast()) @@ -1414,7 +1432,7 @@ bool CBlock::AcceptBlock() // Check that all transactions are finalized foreach(const CTransaction& tx, vtx) - if (!tx.IsFinal(pindexPrev->nHeight+1, GetBlockTime())) + if (!tx.IsFinal(nHeight, GetBlockTime())) return error("AcceptBlock() : contains a non-final transaction"); // Check proof of work @@ -1422,12 +1440,12 @@ bool CBlock::AcceptBlock() return error("AcceptBlock() : incorrect proof of work"); // Check that the block chain matches the known block chain up to a checkpoint - if ((pindexPrev->nHeight+1 == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) || - (pindexPrev->nHeight+1 == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) || - (pindexPrev->nHeight+1 == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) || - (pindexPrev->nHeight+1 == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) || - (pindexPrev->nHeight+1 == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))) - return error("AcceptBlock() : rejected by checkpoint lockin at %d", pindexPrev->nHeight+1); + if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) || + (nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) || + (nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) || + (nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) || + (nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))) + return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight); // Scanback checkpoint lockin for (CBlockIndex* pindex = pindexPrev; pindex->nHeight >= 74000; pindex = pindex->pprev) @@ -2012,13 +2030,13 @@ bool ProcessMessages(CNode* pfrom) } else { - PrintException(&e, "ProcessMessage()"); + PrintExceptionContinue(&e, "ProcessMessage()"); } } catch (std::exception& e) { - PrintException(&e, "ProcessMessage()"); + PrintExceptionContinue(&e, "ProcessMessage()"); } catch (...) { - PrintException(NULL, "ProcessMessage()"); + PrintExceptionContinue(NULL, "ProcessMessage()"); } if (!fRet) @@ -2165,7 +2183,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) multimap mapMix; foreach(CNode* pnode, vNodes) mapMix.insert(make_pair(hashRand = Hash(BEGIN(hashRand), END(hashRand)), pnode)); - int nRelayNodes = 4; + int nRelayNodes = 2; for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) ((*mi).second)->PushAddress(addr); } @@ -2313,7 +2331,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->AddInventoryKnown(inv); bool fMissingInputs = false; - if (tx.AcceptTransaction(true, &fMissingInputs)) + if (tx.AcceptToMemoryPool(true, &fMissingInputs)) { AddToWalletIfMine(tx, NULL); RelayMessage(inv, vMsg); @@ -2333,7 +2351,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CDataStream(vMsg) >> tx; CInv inv(MSG_TX, tx.GetHash()); - if (tx.AcceptTransaction(true)) + if (tx.AcceptToMemoryPool(true)) { printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str()); AddToWalletIfMine(tx, NULL); @@ -2809,8 +2827,9 @@ void BitcoinMiner() map mapTestPool; vector vfAlreadyAdded(mapTransactions.size()); bool fFoundSomething = true; - uint64 nBlockSize = 0; - while (fFoundSomething && nBlockSize < MAX_SIZE/2) + uint64 nBlockSize = 10000; + int nBlockSigOps = 100; + while (fFoundSomething) { fFoundSomething = false; unsigned int n = 0; @@ -2822,7 +2841,10 @@ void BitcoinMiner() if (tx.IsCoinBase() || !tx.IsFinal()) continue; unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK); - if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE - 10000) + if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE) + continue; + int nTxSigOps = tx.GetSigOpCount(); + if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; // Transaction fee based on block size @@ -2835,6 +2857,7 @@ void BitcoinMiner() pblock->vtx.push_back(tx); nBlockSize += nTxSize; + nBlockSigOps += nTxSigOps; vfAlreadyAdded[n] = true; fFoundSomething = true; } @@ -3297,7 +3320,7 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key) // Add the change's private key to wallet if (!key.IsNull() && !AddKey(key)) - throw runtime_error("CommitTransaction() : AddKey failed\n"); + throw runtime_error("CommitTransaction() : AddKey failed"); // Add tx to wallet, because if it has change it's also ours, // otherwise just for transaction history. @@ -3320,7 +3343,7 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key) mapRequestCount[wtxNew.GetHash()] = 0; // Broadcast - if (!wtxNew.AcceptTransaction()) + if (!wtxNew.AcceptToMemoryPool()) { // This must not fail. The transaction has already been signed and recorded. printf("CommitTransaction() : Error: Transaction not valid"); diff --git a/main.h b/main.h index 0fb36eb1..dd86fc19 100644 --- a/main.h +++ b/main.h @@ -15,6 +15,7 @@ class CWalletTx; class CKeyItem; static const unsigned int MAX_BLOCK_SIZE = 1000000; +static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; static const int64 COIN = 100000000; static const int64 CENT = 1000000; static const int64 MAX_MONEY = 21000000 * COIN; @@ -266,7 +267,7 @@ public: str += strprintf("CTxIn("); str += prevout.ToString(); if (prevout.IsNull()) - str += strprintf(", coinbase %s", HexStr(scriptSig.begin(), scriptSig.end(), false).c_str()); + str += strprintf(", coinbase %s", HexStr(scriptSig).c_str()); else str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str()); if (nSequence != UINT_MAX) @@ -474,7 +475,7 @@ public: return error("CTransaction::CheckTransaction() : vin or vout empty"); // Size limits - if (::GetSerializeSize(*this, SER_DISK) > MAX_SIZE) + if (::GetSerializeSize(*this, SER_NETWORK) > MAX_SIZE) return error("CTransaction::CheckTransaction() : size limits failed"); // Check for negative or overflow output values @@ -505,6 +506,16 @@ public: return true; } + int GetSigOpCount() const + { + int n = 0; + foreach(const CTxIn& txin, vin) + n += txin.scriptSig.GetSigOpCount(); + foreach(const CTxOut& txout, vout) + n += txout.scriptPubKey.GetSigOpCount(); + return n; + } + bool IsMine() const { foreach(const CTxOut& txout, vout) @@ -570,11 +581,16 @@ public: if (txout.nValue < CENT) nMinFee = CENT; + // Raise the price as the block approaches full + if (MAX_BLOCK_SIZE/2 <= nBlockSize && nBlockSize < MAX_BLOCK_SIZE) + nMinFee *= MAX_BLOCK_SIZE / (MAX_BLOCK_SIZE - nBlockSize); + if (!MoneyRange(nMinFee)) + nMinFee = MAX_MONEY; + return nMinFee; } - bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL) { CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb"); @@ -639,16 +655,16 @@ public: CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0); bool ClientConnectInputs(); - bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL); + bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL); - bool AcceptTransaction(bool fCheckInputs=true, bool* pfMissingInputs=NULL) + bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL) { CTxDB txdb("r"); - return AcceptTransaction(txdb, fCheckInputs, pfMissingInputs); + return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs); } protected: - bool AddToMemoryPool(); + bool AddToMemoryPoolUnchecked(); public: bool RemoveFromMemoryPool(); }; @@ -721,8 +737,8 @@ public: int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); } bool IsInMainChain() const { return GetDepthInMainChain() > 0; } int GetBlocksToMaturity() const; - bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true); - bool AcceptTransaction() { CTxDB txdb("r"); return AcceptTransaction(txdb); } + bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true); + bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); } }; @@ -852,12 +868,8 @@ public: friend bool operator==(const CTxIndex& a, const CTxIndex& b) { - if (a.pos != b.pos || a.vSpent.size() != b.vSpent.size()) - return false; - for (int i = 0; i < a.vSpent.size(); i++) - if (a.vSpent[i] != b.vSpent[i]) - return false; - return true; + return (a.pos == b.pos && + a.vSpent == b.vSpent); } friend bool operator!=(const CTxIndex& a, const CTxIndex& b) @@ -948,6 +960,14 @@ public: return (int64)nTime; } + int GetSigOpCount() const + { + int n = 0; + foreach(const CTransaction& tx, vtx) + n += tx.GetSigOpCount(); + return n; + } + uint256 BuildMerkleTree() const { diff --git a/makefile.unix b/makefile.unix index 7a38bf04..21994154 100644 --- a/makefile.unix +++ b/makefile.unix @@ -7,11 +7,13 @@ INCLUDEPATHS= \ -I"/usr/local/include/wx-2.9" \ -I"/usr/local/lib/wx/include/gtk2-unicode-debug-static-2.9" +# for wxWidgets 2.9.1, add -l Xxf86vm WXLIBS= \ -Wl,-Bstatic \ -l wx_gtk2ud-2.9 \ -Wl,-Bdynamic \ - -l gtk-x11-2.0 -l SM + -l gtk-x11-2.0 \ + -l SM # for boost 1.37, add -mt to the boost libraries LIBS= \ diff --git a/net.cpp b/net.cpp index 9aaa38f3..d1fdd241 100644 --- a/net.cpp +++ b/net.cpp @@ -25,7 +25,6 @@ CNode* pnodeLocalHost = NULL; uint64 nLocalHostNonce = 0; array vnThreadsRunning; SOCKET hListenSocket = INVALID_SOCKET; -int64 nThreadSocketHandlerHeartbeat = INT64_MAX; vector vNodes; CCriticalSection cs_vNodes; @@ -789,7 +788,6 @@ void ThreadSocketHandler2(void* parg) pnode->Release(); } - nThreadSocketHandlerHeartbeat = GetTime(); Sleep(10); } } @@ -1364,57 +1362,6 @@ void StartNode(void* parg) // Generate coins in the background GenerateBitcoins(fGenerateBitcoins); - - // - // Thread monitoring - // Not really needed anymore, the cause of the hanging was fixed - // - loop - { - Sleep(1000); - if (fShutdown) - return; - if (GetTime() - nThreadSocketHandlerHeartbeat > 15 * 60) - { - // First see if closing sockets will free it - printf("*** ThreadSocketHandler is stopped ***\n"); - CRITICAL_BLOCK(cs_vNodes) - { - foreach(CNode* pnode, vNodes) - { - bool fGot = false; - TRY_CRITICAL_BLOCK(pnode->cs_vRecv) - TRY_CRITICAL_BLOCK(pnode->cs_vSend) - fGot = true; - if (!fGot) - { - printf("*** closing socket\n"); - pnode->CloseSocketDisconnect(); - } - } - } - Sleep(10000); - if (fShutdown) - return; - if (GetTime() - nThreadSocketHandlerHeartbeat < 60) - continue; - - // Hopefully it never comes to this. - // We know it'll always be hung in the recv or send call. - // cs_vRecv or cs_vSend may be left permanently unreleased, - // but we always only use TRY_CRITICAL_SECTION on them. - printf("*** Restarting ThreadSocketHandler ***\n"); - TerminateThread(hThreadSocketHandler, 0); - #ifdef __WXMSW__ - CloseHandle(hThreadSocketHandler); - #endif - vnThreadsRunning[0] = 0; - - // Restart - hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true); - nThreadSocketHandlerHeartbeat = GetTime(); - } - } } bool StopNode() diff --git a/net.h b/net.h index e12a8e11..372e57fb 100644 --- a/net.h +++ b/net.h @@ -117,9 +117,9 @@ public: } // Message size - if (nMessageSize > 0x10000000) + if (nMessageSize > MAX_SIZE) { - printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize); + printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize); return false; } @@ -466,7 +466,6 @@ extern CNode* pnodeLocalHost; extern uint64 nLocalHostNonce; extern array vnThreadsRunning; extern SOCKET hListenSocket; -extern int64 nThreadSocketHandlerHeartbeat; extern vector vNodes; extern CCriticalSection cs_vNodes; diff --git a/script.cpp b/script.cpp index 26c1f4a9..9b30d5a1 100644 --- a/script.cpp +++ b/script.cpp @@ -59,6 +59,13 @@ void MakeSameSize(valtype& vch1, valtype& vch2) // #define stacktop(i) (stack.at(stack.size()+(i))) #define altstacktop(i) (altstack.at(altstack.size()+(i))) +static inline void popstack(vector& stack) +{ + if (stack.empty()) + throw runtime_error("popstack() : stack empty"); + stack.pop_back(); +} + bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType) { @@ -66,6 +73,8 @@ bool EvalScript(vector >& stack, const CScript& script, co CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); + opcodetype opcode; + valtype vchPushValue; vector vfExec; vector altstack; if (script.size() > 10000) @@ -82,13 +91,11 @@ bool EvalScript(vector >& stack, const CScript& script, co // // Read instruction // - opcodetype opcode; - valtype vchPushValue; if (!script.GetOp(pc, opcode, vchPushValue)) return false; if (vchPushValue.size() > 520) return false; - if (opcode > OP_16 && nOpCount++ > 200) + if (opcode > OP_16 && ++nOpCount > 201) return false; if (opcode == OP_CAT || @@ -108,7 +115,7 @@ bool EvalScript(vector >& stack, const CScript& script, co opcode == OP_RSHIFT) return false; - if (fExec && opcode <= OP_PUSHDATA4) + if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) stack.push_back(vchPushValue); else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) @@ -149,14 +156,6 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: break; - case OP_VER: - case OP_VERIF: - case OP_VERNOTIF: - { - return false; - } - break; - case OP_IF: case OP_NOTIF: { @@ -170,7 +169,7 @@ bool EvalScript(vector >& stack, const CScript& script, co fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; - stack.pop_back(); + popstack(stack); } vfExec.push_back(fValue); } @@ -200,7 +199,7 @@ bool EvalScript(vector >& stack, const CScript& script, co return false; bool fValue = CastToBool(stacktop(-1)); if (fValue) - stack.pop_back(); + popstack(stack); else return false; } @@ -221,7 +220,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if (stack.size() < 1) return false; altstack.push_back(stacktop(-1)); - stack.pop_back(); + popstack(stack); } break; @@ -230,15 +229,17 @@ bool EvalScript(vector >& stack, const CScript& script, co if (altstack.size() < 1) return false; stack.push_back(altstacktop(-1)); - altstack.pop_back(); + popstack(altstack); } break; case OP_2DROP: { // (x1 x2 -- ) - stack.pop_back(); - stack.pop_back(); + if (stack.size() < 2) + return false; + popstack(stack); + popstack(stack); } break; @@ -327,7 +328,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (x -- ) if (stack.size() < 1) return false; - stack.pop_back(); + popstack(stack); } break; @@ -368,7 +369,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if (stack.size() < 2) return false; int n = CastToBigNum(stacktop(-1)).getint(); - stack.pop_back(); + popstack(stack); if (n < 0 || n >= stack.size()) return false; valtype vch = stacktop(-n-1); @@ -421,7 +422,7 @@ bool EvalScript(vector >& stack, const CScript& script, co valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); vch1.insert(vch1.end(), vch2.begin(), vch2.end()); - stack.pop_back(); + popstack(stack); if (stacktop(-1).size() > 520) return false; } @@ -443,8 +444,8 @@ bool EvalScript(vector >& stack, const CScript& script, co nEnd = vch.size(); vch.erase(vch.begin() + nEnd, vch.end()); vch.erase(vch.begin(), vch.begin() + nBegin); - stack.pop_back(); - stack.pop_back(); + popstack(stack); + popstack(stack); } break; @@ -464,7 +465,7 @@ bool EvalScript(vector >& stack, const CScript& script, co vch.erase(vch.begin() + nSize, vch.end()); else vch.erase(vch.begin(), vch.end() - nSize); - stack.pop_back(); + popstack(stack); } break; @@ -518,7 +519,7 @@ bool EvalScript(vector >& stack, const CScript& script, co for (int i = 0; i < vch1.size(); i++) vch1[i] ^= vch2[i]; } - stack.pop_back(); + popstack(stack); } break; @@ -537,13 +538,13 @@ bool EvalScript(vector >& stack, const CScript& script, co // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; - stack.pop_back(); - stack.pop_back(); + popstack(stack); + popstack(stack); stack.push_back(fEqual ? vchTrue : vchFalse); if (opcode == OP_EQUALVERIFY) { if (fEqual) - stack.pop_back(); + popstack(stack); else return false; } @@ -578,7 +579,7 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_NOT: bn = (bn == bnZero); break; case OP_0NOTEQUAL: bn = (bn != bnZero); break; } - stack.pop_back(); + popstack(stack); stack.push_back(bn.getvch()); } break; @@ -657,14 +658,14 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break; case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break; } - stack.pop_back(); - stack.pop_back(); + popstack(stack); + popstack(stack); stack.push_back(bn.getvch()); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(-1))) - stack.pop_back(); + popstack(stack); else return false; } @@ -680,9 +681,9 @@ bool EvalScript(vector >& stack, const CScript& script, co CBigNum bn2 = CastToBigNum(stacktop(-2)); CBigNum bn3 = CastToBigNum(stacktop(-1)); bool fValue = (bn2 <= bn1 && bn1 < bn3); - stack.pop_back(); - stack.pop_back(); - stack.pop_back(); + popstack(stack); + popstack(stack); + popstack(stack); stack.push_back(fValue ? vchTrue : vchFalse); } break; @@ -718,7 +719,7 @@ bool EvalScript(vector >& stack, const CScript& script, co uint256 hash = Hash(vch.begin(), vch.end()); memcpy(&vchHash[0], &hash, sizeof(hash)); } - stack.pop_back(); + popstack(stack); stack.push_back(vchHash); } break; @@ -752,13 +753,13 @@ bool EvalScript(vector >& stack, const CScript& script, co bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); - stack.pop_back(); - stack.pop_back(); + popstack(stack); + popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) - stack.pop_back(); + popstack(stack); else return false; } @@ -822,13 +823,13 @@ bool EvalScript(vector >& stack, const CScript& script, co } while (i-- > 0) - stack.pop_back(); + popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) - stack.pop_back(); + popstack(stack); else return false; } @@ -856,8 +857,6 @@ bool EvalScript(vector >& stack, const CScript& script, co return true; } -#undef top - @@ -945,10 +944,7 @@ bool CheckSig(vector vchSig, vector vchPubKey, CSc return false; vchSig.pop_back(); - if (key.Verify(SignatureHash(scriptCode, txTo, nIn, nHashType), vchSig)) - return true; - - return false; + return key.Verify(SignatureHash(scriptCode, txTo, nIn, nHashType), vchSig); } @@ -986,21 +982,19 @@ bool Solver(const CScript& scriptPubKey, vector >& vSo CScript::const_iterator pc2 = script2.begin(); loop { - bool f1 = script1.GetOp(pc1, opcode1, vch1); - bool f2 = script2.GetOp(pc2, opcode2, vch2); - if (!f1 && !f2) + if (pc1 == script1.end() && pc2 == script2.end()) { - // Success + // Found a match reverse(vSolutionRet.begin(), vSolutionRet.end()); return true; } - else if (f1 != f2) - { + if (!script1.GetOp(pc1, opcode1, vch1)) break; - } - else if (opcode2 == OP_PUBKEY) + if (!script2.GetOp(pc2, opcode2, vch2)) + break; + if (opcode2 == OP_PUBKEY) { - if (vch1.size() <= sizeof(uint256)) + if (vch1.size() < 33) break; vSolutionRet.push_back(make_pair(opcode2, vch1)); } @@ -1010,7 +1004,7 @@ bool Solver(const CScript& scriptPubKey, vector >& vSo break; vSolutionRet.push_back(make_pair(opcode2, vch1)); } - else if (opcode1 != opcode2) + else if (opcode1 != opcode2 || vch1 != vch2) { break; } @@ -1068,6 +1062,10 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s scriptSigRet << vchSig << vchPubKey; } } + else + { + return false; + } } } diff --git a/script.h b/script.h index 20d29312..c829ed05 100644 --- a/script.h +++ b/script.h @@ -150,18 +150,11 @@ enum opcodetype - - // multi-byte opcodes - OP_SINGLEBYTE_END = 0xF0, - OP_DOUBLEBYTE_BEGIN = 0xF000, - // template matching params - OP_PUBKEY, - OP_PUBKEYHASH, - - + OP_PUBKEYHASH = 0xfd, + OP_PUBKEY = 0xfe, - OP_INVALIDOPCODE = 0xFFFF, + OP_INVALIDOPCODE = 0xff, }; @@ -304,16 +297,13 @@ inline const char* GetOpName(opcodetype opcode) - // multi-byte opcodes - case OP_SINGLEBYTE_END : return "OP_SINGLEBYTE_END"; - case OP_DOUBLEBYTE_BEGIN : return "OP_DOUBLEBYTE_BEGIN"; - case OP_PUBKEY : return "OP_PUBKEY"; + // template matching params case OP_PUBKEYHASH : return "OP_PUBKEYHASH"; - + case OP_PUBKEY : return "OP_PUBKEY"; case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; default: - return "UNKNOWN_OPCODE"; + return "OP_UNKNOWN"; } }; @@ -325,8 +315,7 @@ inline string ValueString(const vector& vch) if (vch.size() <= 4) return strprintf("%d", CBigNum(vch).getint()); else - return HexNumStr(vch.begin(), vch.end()); - //return string("(") + HexStr(vch.begin(), vch.end()) + string(")"); + return HexStr(vch); } inline string StackString(const vector >& vStack) @@ -363,12 +352,12 @@ protected: CBigNum bn(n); *this << bn.getvch(); } - return (*this); + return *this; } CScript& push_uint64(uint64 n) { - if (n == -1 || (n >= 1 && n <= 16)) + if (n >= 1 && n <= 16) { push_back(n + (OP_1 - 1)); } @@ -377,7 +366,7 @@ protected: CBigNum bn(n); *this << bn.getvch(); } - return (*this); + return *this; } public: @@ -398,7 +387,7 @@ public: { CScript ret = a; ret += b; - return (ret); + return ret; } @@ -419,50 +408,43 @@ public: explicit CScript(const vector& b) { operator<<(b); } - CScript& operator<<(char b) { return (push_int64(b)); } - CScript& operator<<(short b) { return (push_int64(b)); } - CScript& operator<<(int b) { return (push_int64(b)); } - CScript& operator<<(long b) { return (push_int64(b)); } - CScript& operator<<(int64 b) { return (push_int64(b)); } - CScript& operator<<(unsigned char b) { return (push_uint64(b)); } - CScript& operator<<(unsigned int b) { return (push_uint64(b)); } - CScript& operator<<(unsigned short b) { return (push_uint64(b)); } - CScript& operator<<(unsigned long b) { return (push_uint64(b)); } - CScript& operator<<(uint64 b) { return (push_uint64(b)); } + CScript& operator<<(char b) { return push_int64(b); } + CScript& operator<<(short b) { return push_int64(b); } + CScript& operator<<(int b) { return push_int64(b); } + CScript& operator<<(long b) { return push_int64(b); } + CScript& operator<<(int64 b) { return push_int64(b); } + CScript& operator<<(unsigned char b) { return push_uint64(b); } + CScript& operator<<(unsigned int b) { return push_uint64(b); } + CScript& operator<<(unsigned short b) { return push_uint64(b); } + CScript& operator<<(unsigned long b) { return push_uint64(b); } + CScript& operator<<(uint64 b) { return push_uint64(b); } CScript& operator<<(opcodetype opcode) { - if (opcode <= OP_SINGLEBYTE_END) - { - insert(end(), (unsigned char)opcode); - } - else - { - assert(opcode >= OP_DOUBLEBYTE_BEGIN); - insert(end(), (unsigned char)(opcode >> 8)); - insert(end(), (unsigned char)(opcode & 0xFF)); - } - return (*this); + if (opcode < 0 || opcode > 0xff) + throw runtime_error("CScript::operator<<() : invalid opcode"); + insert(end(), (unsigned char)opcode); + return *this; } CScript& operator<<(const uint160& b) { insert(end(), sizeof(b)); insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); - return (*this); + return *this; } CScript& operator<<(const uint256& b) { insert(end(), sizeof(b)); insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); - return (*this); + return *this; } CScript& operator<<(const CBigNum& b) { *this << b.getvch(); - return (*this); + return *this; } CScript& operator<<(const vector& b) @@ -476,14 +458,20 @@ public: insert(end(), OP_PUSHDATA1); insert(end(), (unsigned char)b.size()); } - else + else if (b.size() <= 0xffff) { insert(end(), OP_PUSHDATA2); unsigned short nSize = b.size(); insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); } + else + { + insert(end(), OP_PUSHDATA4); + unsigned int nSize = b.size(); + insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); + } insert(end(), b.begin(), b.end()); - return (*this); + return *this; } CScript& operator<<(const CScript& b) @@ -491,7 +479,7 @@ public: // I'm not sure if this should push the script or concatenate scripts. // If there's ever a use for pushing a script onto a script, delete this member fn assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false)); - return (*this); + return *this; } @@ -499,41 +487,59 @@ public: { // Wrapper so it can be called with either iterator or const_iterator const_iterator pc2 = pc; - bool fRet = GetOp(pc2, opcodeRet, vchRet); + bool fRet = GetOp2(pc2, opcodeRet, &vchRet); + pc = begin() + (pc2 - begin()); + return fRet; + } + + bool GetOp(iterator& pc, opcodetype& opcodeRet) + { + const_iterator pc2 = pc; + bool fRet = GetOp2(pc2, opcodeRet, NULL); pc = begin() + (pc2 - begin()); return fRet; } bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector& vchRet) const + { + return GetOp2(pc, opcodeRet, &vchRet); + } + + bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const + { + return GetOp2(pc, opcodeRet, NULL); + } + + bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, vector* pvchRet) const { opcodeRet = OP_INVALIDOPCODE; - vchRet.clear(); + if (pvchRet) + pvchRet->clear(); if (pc >= end()) return false; // Read instruction + if (end() - pc < 1) + return false; unsigned int opcode = *pc++; - if (opcode >= OP_SINGLEBYTE_END) - { - if (pc + 1 > end()) - return false; - opcode <<= 8; - opcode |= *pc++; - } // Immediate operand if (opcode <= OP_PUSHDATA4) { - unsigned int nSize = opcode; - if (opcode == OP_PUSHDATA1) + unsigned int nSize; + if (opcode < OP_PUSHDATA1) + { + nSize = opcode; + } + else if (opcode == OP_PUSHDATA1) { - if (pc + 1 > end()) + if (end() - pc < 1) return false; nSize = *pc++; } else if (opcode == OP_PUSHDATA2) { - if (pc + 2 > end()) + if (end() - pc < 2) return false; nSize = 0; memcpy(&nSize, &pc[0], 2); @@ -541,14 +547,15 @@ public: } else if (opcode == OP_PUSHDATA4) { - if (pc + 4 > end()) + if (end() - pc < 4) return false; memcpy(&nSize, &pc[0], 4); pc += 4; } - if (pc + nSize > end()) + if (end() - pc < nSize) return false; - vchRet.assign(pc, pc + nSize); + if (pvchRet) + pvchRet->assign(pc, pc + nSize); pc += nSize; } @@ -559,20 +566,34 @@ public: void FindAndDelete(const CScript& b) { + if (b.empty()) + return; iterator pc = begin(); opcodetype opcode; - vector vchPushValue; - int count = 0; do { while (end() - pc >= b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) - { erase(pc, pc + b.size()); - count++; - } } - while (GetOp(pc, opcode, vchPushValue)); - //printf("FindAndDeleted deleted %d items\n", count); /// debug + while (GetOp(pc, opcode)); + } + + + int GetSigOpCount() const + { + int n = 0; + const_iterator pc = begin(); + while (pc < end()) + { + opcodetype opcode; + if (!GetOp(pc, opcode)) + break; + if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY) + n++; + else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY) + n += 20; + } + return n; } @@ -623,7 +644,7 @@ public: void PrintHex() const { - printf("CScript(%s)\n", HexStr(begin(), end()).c_str()); + printf("CScript(%s)\n", HexStr(begin(), end(), true).c_str()); } string ToString() const @@ -631,12 +652,17 @@ public: string str; opcodetype opcode; vector vch; - const_iterator it = begin(); - while (GetOp(it, opcode, vch)) + const_iterator pc = begin(); + while (pc < end()) { if (!str.empty()) str += " "; - if (opcode <= OP_PUSHDATA4) + if (!GetOp(pc, opcode, vch)) + { + str += "[error]"; + return str; + } + if (0 <= opcode && opcode <= OP_PUSHDATA4) str += ValueString(vch); else str += GetOpName(opcode); diff --git a/serialize.h b/serialize.h index e1404b70..5ded6bf0 100644 --- a/serialize.h +++ b/serialize.h @@ -23,7 +23,7 @@ class CAutoFile; static const unsigned int MAX_SIZE = 0x02000000; static const int VERSION = 312; -static const char* pszSubVer = ".0"; +static const char* pszSubVer = ".1"; diff --git a/setup.nsi b/setup.nsi index 3dc1a150..78d83d4e 100644 --- a/setup.nsi +++ b/setup.nsi @@ -7,7 +7,7 @@ RequestExecutionLevel highest # General Symbol Definitions !define REGKEY "SOFTWARE\$(^Name)" -!define VERSION 0.3.10 +!define VERSION 0.3.12 !define COMPANY "Bitcoin project" !define URL http://www.bitcoin.org/ @@ -42,12 +42,12 @@ Var StartMenuGroup !insertmacro MUI_LANGUAGE English # Installer attributes -OutFile bitcoin-0.3.10-win32-setup.exe +OutFile bitcoin-0.3.12-win32-setup.exe InstallDir $PROGRAMFILES\Bitcoin CRCCheck on XPStyle on ShowInstDetails show -VIProductVersion 0.3.10.0 +VIProductVersion 0.3.12.0 VIAddVersionKey ProductName Bitcoin VIAddVersionKey ProductVersion "${VERSION}" VIAddVersionKey CompanyName "${COMPANY}" diff --git a/sha256.cpp b/sha256.cpp index 057f9423..1bba8cf9 100644 --- a/sha256.cpp +++ b/sha256.cpp @@ -87,6 +87,8 @@ static inline void dumpreg(__m128i x, char *msg) { #else #define dumpstate() #endif + + void Double_BlockSHA256(const void* pin, void* pad, const void *pre, unsigned int thash[9][NPAR], const void *init) { unsigned int* In = (unsigned int*)pin; diff --git a/ui.cpp b/ui.cpp index 179b22d6..4d4e8463 100644 --- a/ui.cpp +++ b/ui.cpp @@ -1031,9 +1031,6 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) string strStatus = strprintf(_(" %d connections %d blocks %d transactions"), vNodes.size(), nBestHeight, nTransactionCount); m_statusBar->SetStatusText(strStatus, 2); - if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60) - m_statusBar->SetStatusText(" ERROR: ThreadSocketHandler has stopped", 0); - // Update receiving address string strDefaultAddress = PubKeyToAddress(vchDefaultKey); if (m_textCtrlAddress->GetValue() != strDefaultAddress) diff --git a/ui.h b/ui.h index b78f2064..9769fd70 100644 --- a/ui.h +++ b/ui.h @@ -305,8 +305,8 @@ public: y += 46 + wxString(strMessage2).Freq('\n') * 14; } #ifndef __WXMSW__ - x *= 1.14; - y *= 1.14; + x = x * 114 / 100; + y = y * 114 / 100; #endif SetSize(x, y); } diff --git a/util.cpp b/util.cpp index 2a3e964a..ef2e6834 100644 --- a/util.cpp +++ b/util.cpp @@ -79,7 +79,7 @@ instance_of_cinit; void RandAddSeed() { // Seed with CPU performance counter - int64 nCounter = PerformanceCounter(); + int64 nCounter = GetPerformanceCounter(); RAND_add(&nCounter, sizeof(nCounter), 1.5); memset(&nCounter, 0, sizeof(nCounter)); } @@ -499,23 +499,47 @@ void FormatException(char* pszMessage, std::exception* pex, const char* pszThrea void LogException(std::exception* pex, const char* pszThread) { - char pszMessage[1000]; + char pszMessage[10000]; FormatException(pszMessage, pex, pszThread); printf("\n%s", pszMessage); } void PrintException(std::exception* pex, const char* pszThread) { - char pszMessage[1000]; + char pszMessage[10000]; FormatException(pszMessage, pex, pszThread); printf("\n\n************************\n%s\n", pszMessage); fprintf(stderr, "\n\n************************\n%s\n", pszMessage); + strMiscWarning = pszMessage; #ifdef GUI if (wxTheApp && !fDaemon) - MyMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR); + MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR); #endif throw; - //DebugBreak(); +} + +void ThreadOneMessageBox(string strMessage) +{ + // Skip message boxes if one is already open + static bool fMessageBoxOpen; + if (fMessageBoxOpen) + return; + fMessageBoxOpen = true; + ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION); + fMessageBoxOpen = false; +} + +void PrintExceptionContinue(std::exception* pex, const char* pszThread) +{ + char pszMessage[10000]; + FormatException(pszMessage, pex, pszThread); + printf("\n\n************************\n%s\n", pszMessage); + fprintf(stderr, "\n\n************************\n%s\n", pszMessage); + strMiscWarning = pszMessage; +#ifdef GUI + if (wxTheApp && !fDaemon) + boost::thread(bind(ThreadOneMessageBox, string(pszMessage))); +#endif } @@ -749,7 +773,7 @@ void AddTimeData(unsigned int ip, int64 nTime) if (!fMatch && !fDone) { fDone = true; - string strMessage = _("Warning: Check your system date and time, you may not be able to generate or receive the most recent blocks!"); + string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly."); strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1)); diff --git a/util.h b/util.h index 56b13c0b..22ace616 100644 --- a/util.h +++ b/util.h @@ -151,8 +151,9 @@ int OutputDebugStringF(const char* pszFormat, ...); int my_snprintf(char* buffer, size_t limit, const char* format, ...); string strprintf(const char* format, ...); bool error(const char* format, ...); -void PrintException(std::exception* pex, const char* pszThread); void LogException(std::exception* pex, const char* pszThread); +void PrintException(std::exception* pex, const char* pszThread); +void PrintExceptionContinue(std::exception* pex, const char* pszThread); void ParseString(const string& str, char c, vector& v); string FormatMoney(int64 n, bool fPlus=false); bool ParseMoney(const string& str, int64& nRet); @@ -305,19 +306,20 @@ inline int64 abs64(int64 n) } template -string HexStr(const T itbegin, const T itend, bool fSpaces=true) +string HexStr(const T itbegin, const T itend, bool fSpaces=false) { if (itbegin == itend) return ""; const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); string str; + str.reserve((pend-pbegin) * (fSpaces ? 3 : 2)); for (const unsigned char* p = pbegin; p != pend; p++) str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p); return str; } -inline string HexStr(vector vch, bool fSpaces=true) +inline string HexStr(const vector& vch, bool fSpaces=false) { return HexStr(vch.begin(), vch.end(), fSpaces); } @@ -330,23 +332,29 @@ string HexNumStr(const T itbegin, const T itend, bool f0x=true) const unsigned char* pbegin = (const unsigned char*)&itbegin[0]; const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]); string str = (f0x ? "0x" : ""); + str.reserve(str.size() + (pend-pbegin) * 2); for (const unsigned char* p = pend-1; p >= pbegin; p--) - str += strprintf("%02X", *p); + str += strprintf("%02x", *p); return str; } +inline string HexNumStr(const vector& vch, bool f0x=true) +{ + return HexNumStr(vch.begin(), vch.end(), f0x); +} + template void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true) { printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str()); } -inline void PrintHex(vector vch, const char* pszFormat="%s", bool fSpaces=true) +inline void PrintHex(const vector& vch, const char* pszFormat="%s", bool fSpaces=true) { printf(pszFormat, HexStr(vch, fSpaces).c_str()); } -inline int64 PerformanceCounter() +inline int64 GetPerformanceCounter() { int64 nCounter = 0; #ifdef __WXMSW__ @@ -409,16 +417,16 @@ inline void heapchk() } // Randomize the stack to help protect against buffer overrun exploits -#define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \ - { \ - static char nLoops; \ - if (nLoops <= 0) \ - nLoops = GetRand(20) + 1; \ - if (nLoops-- > 1) \ - { \ - ThreadFn; \ - return; \ - } \ +#define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \ + { \ + static char nLoops; \ + if (nLoops <= 0) \ + nLoops = GetRand(20) + 1; \ + if (nLoops-- > 1) \ + { \ + ThreadFn; \ + return; \ + } \ } #define CATCH_PRINT_EXCEPTION(pszFn) \