From 8c9479c6bbbc38b897dc97de9d04e4d5a5a36730 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Tue, 7 Sep 2010 01:12:53 +0000 Subject: [PATCH 01/10] cleanup, catch some recoverable exceptions and continue -- version 0.3.12 release git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@148 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- cryptopp/secblock.h | 3 +- db.cpp | 7 +- init.cpp | 4 +- irc.cpp | 20 +++++ main.cpp | 99 ++++++++++++++---------- main.h | 50 +++++++++---- makefile.unix | 4 +- net.cpp | 53 ------------- net.h | 5 +- script.cpp | 112 ++++++++++++++-------------- script.h | 178 +++++++++++++++++++++++++------------------- serialize.h | 2 +- setup.nsi | 6 +- sha256.cpp | 2 + ui.cpp | 3 - ui.h | 4 +- util.cpp | 36 +++++++-- util.h | 40 ++++++---- 18 files changed, 350 insertions(+), 278 deletions(-) diff --git a/cryptopp/secblock.h b/cryptopp/secblock.h index d66470e9016..5e3882916a4 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 56ec9ee6eef..6b3af257981 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 af8ad753be5..43a672f5aee 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 daa9a0db618..a520173f1bf 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 76d30373f5e..835b7c7a465 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 0fb36eb1f8c..dd86fc19f78 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 7a38bf0464d..21994154a46 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 9aaa38f32de..d1fdd241bc8 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 e12a8e1129c..372e57fbbcd 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 26c1f4a9345..9b30d5a1a45 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 20d29312bd9..c829ed053ea 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) { - if (pc + 1 > end()) + nSize = opcode; + } + else if (opcode == OP_PUSHDATA1) + { + 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 e1404b70686..5ded6bf0987 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 3dc1a1507e8..78d83d4e543 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 057f9423b7f..1bba8cf93a8 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 179b22d6b46..4d4e8463b4d 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 b78f2064e02..9769fd700de 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 2a3e964afb2..ef2e68344da 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 56b13c0bbf2..22ace616b4f 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) \ From 14002c8eba6fe03bec721bcacf4bed0b3cbca6d5 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Wed, 8 Sep 2010 19:24:32 +0000 Subject: [PATCH 02/10] Gavin Andresen: clean shutdown on SIGTERM git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@149 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- headers.h | 1 + init.cpp | 14 +++++++++++++- net.cpp | 2 ++ util.cpp | 1 + util.h | 1 + 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/headers.h b/headers.h index 682f7ab1a82..31e6712017d 100644 --- a/headers.h +++ b/headers.h @@ -99,6 +99,7 @@ #include #include #include +#include #endif #ifdef BSD #include diff --git a/init.cpp b/init.cpp index 43a672f5aee..95204ad3a08 100644 --- a/init.cpp +++ b/init.cpp @@ -10,7 +10,6 @@ - ////////////////////////////////////////////////////////////////////////////// // // Shutdown @@ -57,6 +56,11 @@ void Shutdown(void* parg) } } +void HandleSIGTERM(int) +{ + fRequestShutdown = true; +} + @@ -130,6 +134,14 @@ bool AppInit2(int argc, char* argv[]) #ifndef __WXMSW__ umask(077); #endif +#ifndef __WXMSW__ + // Clean shutdown on SIGTERM + struct sigaction sa; + sa.sa_handler = HandleSIGTERM; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGTERM, &sa, NULL); +#endif // // Parameters diff --git a/net.cpp b/net.cpp index d1fdd241bc8..1a64a82c149 100644 --- a/net.cpp +++ b/net.cpp @@ -1163,6 +1163,8 @@ void ThreadMessageHandler2(void* parg) // Wait and allow messages to bunch up vnThreadsRunning[2]--; Sleep(100); + if (fRequestShutdown) + Shutdown(NULL); vnThreadsRunning[2]++; if (fShutdown) return; diff --git a/util.cpp b/util.cpp index ef2e68344da..9efa20ede82 100644 --- a/util.cpp +++ b/util.cpp @@ -11,6 +11,7 @@ bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugger = false; char pszSetDataDir[MAX_PATH] = ""; +bool fRequestShutdown = false; bool fShutdown = false; bool fDaemon = false; bool fCommandLine = false; diff --git a/util.h b/util.h index 22ace616b4f..42d1fe460bd 100644 --- a/util.h +++ b/util.h @@ -140,6 +140,7 @@ extern bool fDebug; extern bool fPrintToConsole; extern bool fPrintToDebugger; extern char pszSetDataDir[MAX_PATH]; +extern bool fRequestShutdown; extern bool fShutdown; extern bool fDaemon; extern bool fCommandLine; From 8555125a1a1af68c9a89b7d4f9447d19ed1736ca Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Thu, 9 Sep 2010 01:00:40 +0000 Subject: [PATCH 03/10] try to auto-detect whether to use 128-bit 4-way SSE2 git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@150 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- cryptopp/secblock.h | 4 +-- main.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++- net.cpp | 4 ++- serialize.h | 2 +- 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/cryptopp/secblock.h b/cryptopp/secblock.h index 5e3882916a4..2025757dbb5 100644 --- a/cryptopp/secblock.h +++ b/cryptopp/secblock.h @@ -184,8 +184,8 @@ public: void deallocate(void *p, size_type n) { - //// Bitcoin: can't figure out why this is tripping on a few compiles. - //assert(false); + //// Bitcoin: don't know why this trips, probably a false alarm, depends on the compiler used. + //assert(false); } size_type max_size() const {return 0;} diff --git a/main.cpp b/main.cpp index 835b7c7a465..e3c44145d11 100644 --- a/main.cpp +++ b/main.cpp @@ -2767,6 +2767,68 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit) static const int NPAR = 32; extern void Double_BlockSHA256(const void* pin, void* pout, const void* pinit, unsigned int hash[8][NPAR], const void* init2); +#ifdef __GNUC__ +void CallCPUID(int in, int& aret, int& cret) +{ + int a, c; + asm ( + "mov %2, %%eax; " // in into eax + "cpuid;" + "mov %%eax, %0;" // eax into ret + "mov %%ecx, %1;" // eax into ret + :"=r"(a),"=r"(c) /* output */ + :"r"(in) /* input */ + :"%eax","%ecx" /* clobbered register */ + ); + aret = a; + cret = c; +} + +bool Detect128BitSSE2() +{ + int a, c, nBrand; + CallCPUID(0, a, nBrand); + bool fIntel = (nBrand == 0x6c65746e); // ntel + bool fAMD = (nBrand == 0x444d4163); // cAMD + + struct + { + unsigned int nStepping : 4; + unsigned int nModel : 4; + unsigned int nFamily : 4; + unsigned int nProcessorType : 2; + unsigned int nUnused : 2; + unsigned int nExtendedModel : 4; + unsigned int nExtendedFamily : 8; + } + cpu; + CallCPUID(1, a, c); + memcpy(&cpu, &a, sizeof(cpu)); + int nFamily = cpu.nExtendedFamily + cpu.nFamily; + int nModel = cpu.nExtendedModel*16 + cpu.nModel; + + // We need Intel Nehalem or AMD K10 or better for 128bit SSE2 + // Nehalem = i3/i5/i7 and some Xeon + // K10 = Opterons with 4 or more cores, Phenom, Phenom II, Athlon II + // Intel Core i5 family 6, model 26 or 30 + // Intel Core i7 family 6, model 26 or 30 + // Intel Core i3 family 6, model 37 + // AMD Phenom family 16, model 10 + bool fUseSSE2 = ((fIntel && nFamily * 10000 + nModel >= 60026) || + (fAMD && nFamily * 10000 + nModel >= 160010)); + + static bool fPrinted; + if (!fPrinted) + { + fPrinted = true; + printf("CPUID %08x family %d, model %d, stepping %d, fUseSSE2=%d\n", nBrand, nFamily, nModel, cpu.nStepping, fUseSSE2); + } + return fUseSSE2; +} +#else +bool Detect128BitSSE2() { return false; } +#endif + @@ -2774,6 +2836,9 @@ void BitcoinMiner() { printf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); + bool f4WaySSE2 = Detect128BitSSE2(); + if (mapArgs.count("-4way")) + f4WaySSE2 = (mapArgs["-4way"] != "0"); CKey key; key.MakeNewKey(); @@ -2913,7 +2978,6 @@ void BitcoinMiner() // // Search // - bool f4WaySSE2 = mapArgs.count("-4way"); int64 nStart = GetTime(); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); uint256 hashbuf[2]; diff --git a/net.cpp b/net.cpp index 1a64a82c149..82b3ffb157f 100644 --- a/net.cpp +++ b/net.cpp @@ -1160,7 +1160,9 @@ void ThreadMessageHandler2(void* parg) pnode->Release(); } - // Wait and allow messages to bunch up + // Wait and allow messages to bunch up. + // Reduce vnThreadsRunning so StopNode has permission to exit while + // we're sleeping, but we must always check fShutdown after doing this. vnThreadsRunning[2]--; Sleep(100); if (fRequestShutdown) diff --git a/serialize.h b/serialize.h index 5ded6bf0987..2b88d353605 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 = ".1"; +static const char* pszSubVer = ".2"; From 00728c24e7866963c78360c1df8c182f3c19c2e0 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Fri, 10 Sep 2010 16:58:59 +0000 Subject: [PATCH 04/10] fix problem sending the last cent with sub-cent fractional change git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@151 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- main.cpp | 9 +++++---- serialize.h | 2 +- ui.cpp | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/main.cpp b/main.cpp index e3c44145d11..3919d7e850c 100644 --- a/main.cpp +++ b/main.cpp @@ -2774,8 +2774,8 @@ void CallCPUID(int in, int& aret, int& cret) asm ( "mov %2, %%eax; " // in into eax "cpuid;" - "mov %%eax, %0;" // eax into ret - "mov %%ecx, %1;" // eax into ret + "mov %%eax, %0;" // eax into a + "mov %%ecx, %1;" // eax into c :"=r"(a),"=r"(c) /* output */ :"r"(in) /* input */ :"%eax","%ecx" /* clobbered register */ @@ -3311,7 +3311,8 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey)); // Fill a vout back to self with any change - if (nValueIn > nTotalValue) + int64 nChange = nValueIn - nTotalValue; + if (nChange >= CENT) { // Note: We use a new key here to keep it from being obvious which side is the change. // The drawback is that by not reusing a previous key, the change may be lost if a @@ -3330,7 +3331,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK scriptChange.SetBitcoinAddress(keyRet.GetPubKey()); else scriptChange << keyRet.GetPubKey() << OP_CHECKSIG; - wtxNew.vout.push_back(CTxOut(nValueIn - nTotalValue, scriptChange)); + wtxNew.vout.push_back(CTxOut(nChange, scriptChange)); } // Fill a vout to the payee diff --git a/serialize.h b/serialize.h index 2b88d353605..712d6c53053 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 = ".2"; +static const char* pszSubVer = ".3"; diff --git a/ui.cpp b/ui.cpp index 4d4e8463b4d..7916f677530 100644 --- a/ui.cpp +++ b/ui.cpp @@ -184,7 +184,7 @@ int ThreadSafeMessageBox(const string& message, const string& caption, int style bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent) { - if (nFeeRequired == 0 || fDaemon) + if (nFeeRequired < CENT || fDaemon) return true; string strMessage = strprintf( _("This transaction is over the size limit. You can still send it for a fee of %s, " From 2323664a37f9336380741399b4c731c22478c617 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Fri, 10 Sep 2010 18:07:48 +0000 Subject: [PATCH 05/10] fix build on non-intel architectures, thanks teknohog git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@152 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 3919d7e850c..8d2fdde0ea9 100644 --- a/main.cpp +++ b/main.cpp @@ -2767,7 +2767,7 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit) static const int NPAR = 32; extern void Double_BlockSHA256(const void* pin, void* pout, const void* pinit, unsigned int hash[8][NPAR], const void* init2); -#ifdef __GNUC__ +#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) void CallCPUID(int in, int& aret, int& cret) { int a, c; From c8ad9b8375f5308bb46a124f096a80926ea42fba Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Sun, 12 Sep 2010 17:30:15 +0000 Subject: [PATCH 06/10] dropped DB_PRIVATE from dbenv.open git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@153 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- db.cpp | 1 - serialize.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/db.cpp b/db.cpp index 6b3af257981..df500cadb87 100644 --- a/db.cpp +++ b/db.cpp @@ -77,7 +77,6 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL) DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD | - DB_PRIVATE | DB_RECOVER, S_IRUSR | S_IWUSR); if (ret > 0) diff --git a/serialize.h b/serialize.h index 712d6c53053..6c636e1b8b5 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 = ".3"; +static const char* pszSubVer = ".4"; From 71cc095cb26c4967ed9e9ebf89b6eb1e685c3844 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Mon, 13 Sep 2010 22:14:24 +0000 Subject: [PATCH 07/10] reorganize BitcoinMiner to make it easier to add different SHA256 routines git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@154 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- main.cpp | 233 +++++++++++++++++++++++++++------------------------- main.h | 3 +- serialize.h | 2 +- sha256.cpp | 52 +++++++++++- 4 files changed, 176 insertions(+), 114 deletions(-) diff --git a/main.cpp b/main.cpp index 8d2fdde0ea9..c26755f72fc 100644 --- a/main.cpp +++ b/main.cpp @@ -2392,13 +2392,11 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) else if (strCommand == "getaddr") { - // This includes all nodes that are currently online, - // since they rebroadcast an addr every 24 hours + // Nodes rebroadcast an addr every 24 hours pfrom->vAddrToSend.clear(); - int64 nSince = GetAdjustedTime() - 12 * 60 * 60; // in the last 12 hours + int64 nSince = GetAdjustedTime() - 6 * 60 * 60; // in the last 6 hours CRITICAL_BLOCK(cs_mapAddresses) { - unsigned int nSize = mapAddresses.size(); foreach(const PAIRTYPE(vector, CAddress)& item, mapAddresses) { if (fShutdown) @@ -2738,35 +2736,6 @@ void ThreadBitcoinMiner(void* parg) printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]); } -int FormatHashBlocks(void* pbuffer, unsigned int len) -{ - unsigned char* pdata = (unsigned char*)pbuffer; - unsigned int blocks = 1 + ((len + 8) / 64); - unsigned char* pend = pdata + 64 * blocks; - memset(pdata + len, 0, 64 * blocks - len); - pdata[len] = 0x80; - unsigned int bits = len * 8; - pend[-1] = (bits >> 0) & 0xff; - pend[-2] = (bits >> 8) & 0xff; - pend[-3] = (bits >> 16) & 0xff; - pend[-4] = (bits >> 24) & 0xff; - return blocks; -} - -using CryptoPP::ByteReverse; - -static const unsigned int pSHA256InitState[8] = -{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; - -inline void SHA256Transform(void* pstate, void* pinput, const void* pinit) -{ - memcpy(pstate, pinit, 32); - CryptoPP::SHA256::Transform((CryptoPP::word32*)pstate, (CryptoPP::word32*)pinput); -} - -static const int NPAR = 32; -extern void Double_BlockSHA256(const void* pin, void* pout, const void* pinit, unsigned int hash[8][NPAR], const void* init2); - #if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) void CallCPUID(int in, int& aret, int& cret) { @@ -2829,6 +2798,67 @@ bool Detect128BitSSE2() bool Detect128BitSSE2() { return false; } #endif +int FormatHashBlocks(void* pbuffer, unsigned int len) +{ + unsigned char* pdata = (unsigned char*)pbuffer; + unsigned int blocks = 1 + ((len + 8) / 64); + unsigned char* pend = pdata + 64 * blocks; + memset(pdata + len, 0, 64 * blocks - len); + pdata[len] = 0x80; + unsigned int bits = len * 8; + pend[-1] = (bits >> 0) & 0xff; + pend[-2] = (bits >> 8) & 0xff; + pend[-3] = (bits >> 16) & 0xff; + pend[-4] = (bits >> 24) & 0xff; + return blocks; +} + +using CryptoPP::ByteReverse; + +static const unsigned int pSHA256InitState[8] = +{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +inline void SHA256Transform(void* pstate, void* pinput, const void* pinit) +{ + memcpy(pstate, pinit, 32); + CryptoPP::SHA256::Transform((CryptoPP::word32*)pstate, (CryptoPP::word32*)pinput); +} + +// +// ScanHash scans nonces looking for a hash with at least some zero bits. +// It operates on big endian data. Caller does the byte reversing. +// All input buffers are 16-byte aligned. nNonce is usually preserved +// between calls, but periodically or if nNonce is above 0xff000000, +// the block is rebuilt and nNonce starts over at zero. +// +unsigned int ScanHash_CryptoPP(char* pmidstate, char* pblock, char* phash1, char* phash, unsigned int& nHashesDone) +{ + unsigned int& nNonce = *(unsigned int*)(pblock + 12); + for (;;) + { + // Crypto++ SHA-256 + // Hash pblock using pmidstate as the starting state into + // preformatted buffer phash1, then hash phash1 into phash + nNonce++; + SHA256Transform(phash1, pblock, pmidstate); + SHA256Transform(phash, phash1, pSHA256InitState); + + // Return the nonce if the hash has at least some zero bits, + // caller will check if it has enough to reach the target + if (((unsigned short*)phash)[14] == 0) + return nNonce; + + // If nothing found after trying for a while, return -1 + if ((nNonce & 0xffff) == 0) + { + nHashesDone = 0xffff+1; + return -1; + } + } +} + +extern unsigned int ScanHash_4WaySSE2(char* pmidstate, char* pblock, char* phash1, char* phash, unsigned int& nHashesDone); + @@ -2883,7 +2913,7 @@ void BitcoinMiner() // Add our coinbase tx as first transaction pblock->vtx.push_back(txNew); - // Collect the latest transactions into the block + // Collect memory pool transactions into the block int64 nFees = 0; CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_mapTransactions) @@ -2891,9 +2921,9 @@ void BitcoinMiner() CTxDB txdb("r"); map mapTestPool; vector vfAlreadyAdded(mapTransactions.size()); - bool fFoundSomething = true; uint64 nBlockSize = 10000; int nBlockSigOps = 100; + bool fFoundSomething = true; while (fFoundSomething) { fFoundSomething = false; @@ -2984,46 +3014,28 @@ void BitcoinMiner() uint256& hash = *alignup<16>(hashbuf); loop { + unsigned int nHashesDone = 0; + unsigned int nNonceFound; + #ifdef FOURWAYSSE2 if (f4WaySSE2) - { - // tcatm's 4-way SSE2 SHA-256 - tmp.block.nNonce += NPAR; - unsigned int thashbuf[9][NPAR]; - unsigned int (&thash)[9][NPAR] = *alignup<16>(&thashbuf); - Double_BlockSHA256((char*)&tmp.block + 64, &tmp.hash1, &midstate, thash, pSHA256InitState); - ((unsigned short*)&hash)[14] = 0xffff; - for (int j = 0; j < NPAR; j++) - { - if (thash[7][j] == 0) - { - for (int i = 0; i < sizeof(hash)/4; i++) - ((unsigned int*)&hash)[i] = thash[i][j]; - pblock->nNonce = ByteReverse(tmp.block.nNonce + j); - } - } - } + // tcatm's 4-way 128-bit SSE2 SHA-256 + nNonceFound = ScanHash_4WaySSE2((char*)&midstate, (char*)&tmp.block + 64, (char*)&tmp.hash1, (char*)&hash, nHashesDone); else #endif - { // Crypto++ SHA-256 - tmp.block.nNonce++; - SHA256Transform(&tmp.hash1, (char*)&tmp.block + 64, &midstate); - SHA256Transform(&hash, &tmp.hash1, pSHA256InitState); - } + nNonceFound = ScanHash_CryptoPP((char*)&midstate, (char*)&tmp.block + 64, (char*)&tmp.hash1, (char*)&hash, nHashesDone); - if (((unsigned short*)&hash)[14] == 0) + // Check if something found + if (nNonceFound != -1) { - // Byte swap the result after preliminary check for (int i = 0; i < sizeof(hash)/4; i++) ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]); if (hash <= hashTarget) { -#ifdef FOURWAYSSE2 - if (!f4WaySSE2) -#endif - pblock->nNonce = ByteReverse(tmp.block.nNonce); + // Found a solution + pblock->nNonce = ByteReverse(nNonceFound); assert(hash == pblock->GetHash()); //// debug print @@ -3059,62 +3071,57 @@ void BitcoinMiner() } } - // Update nTime every few seconds - const unsigned int nMask = 0xffff; - const int nHashesPerCycle = (nMask+1); - if ((tmp.block.nNonce & nMask) == 0) + // Meter hashes/sec + static int64 nHashCounter; + if (nHPSTimerStart == 0) { - // Meter hashes/sec - static int nCycleCounter; - if (nHPSTimerStart == 0) + nHPSTimerStart = GetTimeMillis(); + nHashCounter = 0; + } + else + nHashCounter += nHashesDone; + if (GetTimeMillis() - nHPSTimerStart > 4000) + { + static CCriticalSection cs; + CRITICAL_BLOCK(cs) { - nHPSTimerStart = GetTimeMillis(); - nCycleCounter = 0; - } - else - nCycleCounter++; - if (GetTimeMillis() - nHPSTimerStart > 4000) - { - static CCriticalSection cs; - CRITICAL_BLOCK(cs) + if (GetTimeMillis() - nHPSTimerStart > 4000) { - if (GetTimeMillis() - nHPSTimerStart > 4000) + dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); + nHPSTimerStart = GetTimeMillis(); + nHashCounter = 0; + string strStatus = strprintf(" %.0f khash/s", dHashesPerSec/1000.0); + UIThreadCall(bind(CalledSetStatusBar, strStatus, 0)); + static int64 nLogTime; + if (GetTime() - nLogTime > 30 * 60) { - dHashesPerSec = 1000.0 * nHashesPerCycle * nCycleCounter / (GetTimeMillis() - nHPSTimerStart); - nHPSTimerStart = GetTimeMillis(); - nCycleCounter = 0; - string strStatus = strprintf(" %.0f khash/s", dHashesPerSec/1000.0); - UIThreadCall(bind(CalledSetStatusBar, strStatus, 0)); - static int64 nLogTime; - if (GetTime() - nLogTime > 30 * 60) - { - nLogTime = GetTime(); - printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str()); - printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[3], dHashesPerSec/1000.0); - } + nLogTime = GetTime(); + printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str()); + printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[3], dHashesPerSec/1000.0); } } } - - // Check for stop or if block needs to be rebuilt - if (fShutdown) - return; - if (!fGenerateBitcoins) - return; - if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors) - return; - if (vNodes.empty()) - break; - if (tmp.block.nNonce == 0) - break; - if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60) - break; - if (pindexPrev != pindexBest) - break; - - pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); - tmp.block.nTime = ByteReverse(pblock->nTime); } + + // Check for stop or if block needs to be rebuilt + if (fShutdown) + return; + if (!fGenerateBitcoins) + return; + if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors) + return; + if (vNodes.empty()) + break; + if (tmp.block.nNonce >= 0xff000000) + break; + if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60) + break; + if (pindexPrev != pindexBest) + break; + + // Update nTime every few seconds + pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + tmp.block.nTime = ByteReverse(pblock->nTime); } } } @@ -3352,6 +3359,10 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK if (!SignSignature(*pcoin, wtxNew, nIn++)) return false; + // Limit size + if (::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK) >= MAX_BLOCK_SIZE_GEN/5) + return false; + // Check that enough fee is included if (nFee < wtxNew.GetMinFee()) { diff --git a/main.h b/main.h index dd86fc19f78..0082d5d065b 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 unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; static const int64 COIN = 100000000; static const int64 CENT = 1000000; @@ -475,7 +476,7 @@ public: return error("CTransaction::CheckTransaction() : vin or vout empty"); // Size limits - if (::GetSerializeSize(*this, SER_NETWORK) > MAX_SIZE) + if (::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE) return error("CTransaction::CheckTransaction() : size limits failed"); // Check for negative or overflow output values diff --git a/serialize.h b/serialize.h index 6c636e1b8b5..e9f7e2db789 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 = ".4"; +static const char* pszSubVer = ".5"; diff --git a/sha256.cpp b/sha256.cpp index 1bba8cf93a8..56a89260cb6 100644 --- a/sha256.cpp +++ b/sha256.cpp @@ -2,6 +2,8 @@ // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. +// tcatm's 4-way 128-bit SSE2 SHA-256 + #ifdef FOURWAYSSE2 #include @@ -13,6 +15,8 @@ #define NPAR 32 +extern void DoubleBlockSHA256(const void* pin, void* pout, const void* pinit, unsigned int hash[8][NPAR], const void* init2); + static const unsigned int sha256_consts[] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, /* 0 */ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -88,8 +92,54 @@ static inline void dumpreg(__m128i x, char *msg) { #define dumpstate() #endif +// Align by increasing pointer, must have extra space at end of buffer +template +T* alignup(T* p) +{ + union + { + T* ptr; + size_t n; + } u; + u.ptr = p; + u.n = (u.n + (nBytes-1)) & ~(nBytes-1); + return u.ptr; +} -void Double_BlockSHA256(const void* pin, void* pad, const void *pre, unsigned int thash[9][NPAR], const void *init) +static const unsigned int pSHA256InitState[8] = +{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + + +unsigned int ScanHash_4WaySSE2(char* pmidstate, char* pblock, char* phash1, char* phash, unsigned int& nHashesDone) +{ + unsigned int& nNonce = *(unsigned int*)(pblock + 12); + for (;;) + { + nNonce += NPAR; + unsigned int thashbuf[9][NPAR]; + unsigned int (&thash)[9][NPAR] = *alignup<16>(&thashbuf); + DoubleBlockSHA256(pblock, phash1, pmidstate, thash, pSHA256InitState); + + for (int j = 0; j < NPAR; j++) + { + if (thash[7][j] == 0) + { + for (int i = 0; i < 32/4; i++) + ((unsigned int*)phash)[i] = thash[i][j]; + return nNonce + j; + } + } + + if ((nNonce & 0xffff) == 0) + { + nHashesDone = 0xffff+1; + return -1; + } + } +} + + +void DoubleBlockSHA256(const void* pin, void* pad, const void *pre, unsigned int thash[9][NPAR], const void *init) { unsigned int* In = (unsigned int*)pin; unsigned int* Pad = (unsigned int*)pad; From fe37c350185c946cb735d1415c124657e7839558 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Wed, 15 Sep 2010 22:10:13 +0000 Subject: [PATCH 08/10] config option -rpcallowip= to accept json-rpc connections from another machine git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@155 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- main.cpp | 5 ----- rpc.cpp | 24 ++++++++++++++++++------ serialize.h | 2 +- util.cpp | 48 +++++++++++++++++++++++++++++++++++++++--------- util.h | 19 ++++++++++++++++++- 5 files changed, 76 insertions(+), 22 deletions(-) diff --git a/main.cpp b/main.cpp index c26755f72fc..5b7829e8837 100644 --- a/main.cpp +++ b/main.cpp @@ -3170,11 +3170,6 @@ int64 GetBalance() } -int GetRandInt(int nMax) -{ - return GetRand(nMax); -} - bool SelectCoins(int64 nTargetValue, set& setCoinsRet) { setCoinsRet.clear(); diff --git a/rpc.cpp b/rpc.cpp index 0970c87b2d8..9a4757390fe 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -783,8 +783,9 @@ int ReadHTTPStatus(tcp::iostream& stream) getline(stream, str); vector vWords; boost::split(vWords, str, boost::is_any_of(" ")); - int nStatus = atoi(vWords[1].c_str()); - return nStatus; + if (vWords.size() < 2) + return 500; + return atoi(vWords[1].c_str()); } int ReadHTTPHeader(tcp::iostream& stream, map& mapHeadersRet) @@ -918,6 +919,17 @@ string JSONRPCReply(const Value& result, const Value& error, const Value& id) return write_string(Value(reply), false) + "\n"; } +bool ClientAllowed(const string& strAddress) +{ + if (strAddress == asio::ip::address_v4::loopback().to_string()) + return true; + const vector& vAllow = mapMultiArgs["-rpcallowip"]; + foreach(string strAllow, vAllow) + if (WildcardMatch(strAddress, strAllow)) + return true; + return false; +} + @@ -962,7 +974,7 @@ void ThreadRPCServer2(void* parg) // Bind to loopback 127.0.0.1 so the socket can only be accessed locally boost::asio::io_service io_service; - tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 8332); + tcp::endpoint endpoint(mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback(), 8332); tcp::acceptor acceptor(io_service, endpoint); loop @@ -976,8 +988,8 @@ void ThreadRPCServer2(void* parg) if (fShutdown) return; - // Shouldn't be possible for anyone else to connect, but just in case - if (peer.address().to_string() != "127.0.0.1") + // Restrict callers by IP + if (!ClientAllowed(peer.address().to_string())) continue; // Receive request @@ -1090,7 +1102,7 @@ Object CallRPC(const string& strMethod, const Array& params) GetConfigFile().c_str())); // Connect to localhost - tcp::iostream stream("127.0.0.1", "8332"); + tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), "8332"); if (stream.fail()) throw runtime_error("couldn't connect to server"); diff --git a/serialize.h b/serialize.h index e9f7e2db789..b3ab9b5e280 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 = ".5"; +static const char* pszSubVer = ".6"; diff --git a/util.cpp b/util.cpp index 9efa20ede82..b63b795b801 100644 --- a/util.cpp +++ b/util.cpp @@ -127,6 +127,11 @@ uint64 GetRand(uint64 nMax) return (nRand % nMax); } +int GetRandInt(int nMax) +{ + return GetRand(nMax); +} + @@ -405,7 +410,7 @@ vector ParseHex(const char* psz) return vch; } -vector ParseHex(const std::string& str) +vector ParseHex(const string& str) { return ParseHex(str.c_str()); } @@ -473,6 +478,34 @@ const char* wxGetTranslation(const char* pszEnglish) } +bool WildcardMatch(const char* psz, const char* mask) +{ + loop + { + switch (*mask) + { + case '\0': + return (*psz == '\0'); + case '*': + return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask)); + case '?': + if (*psz == '\0') + return false; + break; + default: + if (*psz != *mask) + return false; + break; + } + psz++; + mask++; + } +} + +bool WildcardMatch(const string& str, const string& mask) +{ + return WildcardMatch(str.c_str(), mask.c_str()); +} @@ -650,7 +683,7 @@ string GetDataDir() string GetConfigFile() { namespace fs = boost::filesystem; - fs::path pathConfig(mapArgs.count("-conf") ? mapArgs["-conf"] : string("bitcoin.conf")); + fs::path pathConfig(GetArg("-conf", "bitcoin.conf")); if (!pathConfig.is_complete()) pathConfig = fs::path(GetDataDir()) / pathConfig; return pathConfig.string(); @@ -718,13 +751,10 @@ void ShrinkDebugFile() // // "Never go to sea with two chronometers; take one or three." -// Our three chronometers are: +// Our three time sources are: // - System clock -// - Median of other server's clocks -// - NTP servers -// -// note: NTP isn't implemented yet, so until then we just use the median -// of other nodes clocks to correct ours. +// - Median of other nodes's clocks +// - The user (asking the user to fix the system clock if the first two disagree) // int64 GetTime() { @@ -768,7 +798,7 @@ void AddTimeData(unsigned int ip, int64 nTime) // If nobody else has the same time as us, give a warning bool fMatch = false; foreach(int64 nOffset, vTimeOffsets) - if (nOffset != 0 && abs64(nOffset) < 10 * 60) + if (nOffset != 0 && abs64(nOffset) < 5 * 60) fMatch = true; static bool fDone; if (!fMatch && !fDone) diff --git a/util.h b/util.h index 42d1fe460bd..2e6bf2a6051 100644 --- a/util.h +++ b/util.h @@ -160,9 +160,11 @@ string FormatMoney(int64 n, bool fPlus=false); bool ParseMoney(const string& str, int64& nRet); bool ParseMoney(const char* pszIn, int64& nRet); vector ParseHex(const char* psz); -vector ParseHex(const std::string& str); +vector ParseHex(const string& str); void ParseParameters(int argc, char* argv[]); const char* wxGetTranslation(const char* psz); +bool WildcardMatch(const char* psz, const char* mask); +bool WildcardMatch(const string& str, const string& mask); int GetFilesize(FILE* file); void GetDataDir(char* pszDirRet); string GetConfigFile(); @@ -173,6 +175,7 @@ string MyGetSpecialFolderPath(int nFolder, bool fCreate); string GetDefaultDataDir(); string GetDataDir(); void ShrinkDebugFile(); +int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); int64 GetTime(); int64 GetAdjustedTime(); @@ -399,6 +402,20 @@ inline bool IsSwitchChar(char c) #endif } +inline string GetArg(const string& strArg, const string& strDefault) +{ + if (mapArgs.count(strArg)) + return mapArgs[strArg]; + return strDefault; +} + +inline int64 GetArg(const string& strArg, int64 nDefault) +{ + if (mapArgs.count(strArg)) + return atoi64(mapArgs[strArg]); + return nDefault; +} + From 6aeb45187b9bdc824fa37aee98aa99d472b6f060 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Sun, 19 Sep 2010 21:20:34 +0000 Subject: [PATCH 09/10] only accept transactions sent by IP address if -allowreceivebyip is specified git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@156 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- main.cpp | 38 +++++++++++++++++++++++--------------- serialize.h | 2 +- ui.cpp | 8 ++++++-- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/main.cpp b/main.cpp index 5b7829e8837..d41801d9e95 100644 --- a/main.cpp +++ b/main.cpp @@ -1374,9 +1374,13 @@ 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_NETWORK) > MAX_SIZE) + if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE) return error("CheckBlock() : size limits failed"); + // Check proof of work matches claimed amount + if (!CheckProofOfWork(GetHash(), nBits)) + return error("CheckBlock() : proof of work failed"); + // Check timestamp if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60) return error("CheckBlock() : block timestamp too far in the future"); @@ -1393,9 +1397,9 @@ bool CBlock::CheckBlock() const if (!tx.CheckTransaction()) return error("CheckBlock() : CheckTransaction failed"); - // Check proof of work matches claimed amount - if (!CheckProofOfWork(GetHash(), nBits)) - return error("CheckBlock() : proof of work failed"); + // Check that it's not full of nonstandard transactions + if (GetSigOpCount() > MAX_BLOCK_SIGOPS) + return error("CheckBlock() : too many nonstandard transactions"); // Check merkleroot if (hashMerkleRoot != BuildMerkleTree()) @@ -1418,13 +1422,9 @@ bool CBlock::AcceptBlock() 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 proof of work + if (nBits != GetNextWorkRequired(pindexPrev)) + return error("AcceptBlock() : incorrect proof of work"); // Check timestamp against prev if (GetBlockTime() <= pindexPrev->GetMedianTimePast()) @@ -1435,10 +1435,6 @@ bool CBlock::AcceptBlock() if (!tx.IsFinal(nHeight, GetBlockTime())) return error("AcceptBlock() : contains a non-final transaction"); - // Check proof of work - if (nBits != GetNextWorkRequired(pindexPrev)) - return error("AcceptBlock() : incorrect proof of work"); - // Check that the block chain matches the known block chain up to a checkpoint if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) || (nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) || @@ -2415,6 +2411,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CWalletTx order; vRecv >> hashReply >> order; + if (!mapArgs.count("-allowreceivebyip") || mapArgs["-allowreceivebyip"] == "0") + { + pfrom->PushMessage("reply", hashReply, (int)2, string("")); + return true; + } + /// we have a chance to check the order here // Keep giving the same key to the same ip until they use it @@ -2435,6 +2437,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) vRecv >> hashReply >> wtxNew; wtxNew.fFromMe = false; + if (!mapArgs.count("-allowreceivebyip") || mapArgs["-allowreceivebyip"] == "0") + { + pfrom->PushMessage("reply", hashReply, (int)2); + return true; + } + // Broadcast if (!wtxNew.AcceptWalletTransaction()) { diff --git a/serialize.h b/serialize.h index b3ab9b5e280..a88e312c8c7 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 = ".6"; +static const char* pszSubVer = ".7"; diff --git a/ui.cpp b/ui.cpp index 7916f677530..80cf08841fb 100644 --- a/ui.cpp +++ b/ui.cpp @@ -2186,8 +2186,12 @@ void CSendingDialog::OnReply2(CDataStream& vRecv) if (nRet > 0) { string strMessage; - vRecv >> strMessage; - Error(_("Transfer was not accepted")); + if (!vRecv.empty()) + vRecv >> strMessage; + if (nRet == 2) + Error(_("Recipient is not accepting transactions sent by IP address")); + else + Error(_("Transfer was not accepted")); //// todo: enlarge the window and enable a hidden white box to put seller's message return; } From 8d13ca1f11c206188e016546e5ebf7c18c884021 Mon Sep 17 00:00:00 2001 From: s_nakamoto Date: Thu, 23 Sep 2010 16:01:44 +0000 Subject: [PATCH 10/10] changed free transactions per block threshold git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@157 1a98c847-1fd6-4fd8-948a-caf3550aa51b --- main.cpp | 4 ++-- main.h | 33 ++++++++++++++++++++------------- serialize.h | 2 +- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/main.cpp b/main.cpp index d41801d9e95..10931f9d19f 100644 --- a/main.cpp +++ b/main.cpp @@ -2929,7 +2929,7 @@ void BitcoinMiner() CTxDB txdb("r"); map mapTestPool; vector vfAlreadyAdded(mapTransactions.size()); - uint64 nBlockSize = 10000; + uint64 nBlockSize = 1000; int nBlockSigOps = 100; bool fFoundSomething = true; while (fFoundSomething) @@ -2944,7 +2944,7 @@ void BitcoinMiner() if (tx.IsCoinBase() || !tx.IsFinal()) continue; unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK); - if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE) + if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN) continue; int nTxSigOps = tx.GetSigOpCount(); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) diff --git a/main.h b/main.h index 0082d5d065b..95e946a8981 100644 --- a/main.h +++ b/main.h @@ -565,15 +565,16 @@ public: { // Base fee is 1 cent per kilobyte unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK); + unsigned int nNewBlockSize = nBlockSize + nBytes; int64 nMinFee = (1 + (int64)nBytes / 1000) * CENT; - // Transactions under 60K are free as long as block size is under 80K - // (about 27,000bc if made of 50bc inputs) - if (nBytes < 60000 && nBlockSize < 80000) + // Transactions under 25K are free as long as block size is under 40K + // (about 11,000bc if made of 50bc inputs) + if (nBytes < 25000 && nNewBlockSize < 40000) nMinFee = 0; - // Transactions under 3K are free as long as block size is under 200K - if (nBytes < 3000 && nBlockSize < 200000) + // Transactions under 3K are free as long as block size is under 50K + if (nBytes < 3000 && nNewBlockSize < 50000) nMinFee = 0; // To limit dust spam, require a 0.01 fee if any output is less than 0.01 @@ -583,11 +584,15 @@ public: 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 (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) + { + if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN) + return MAX_MONEY; + nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize); + } + if (!MoneyRange(nMinFee)) nMinFee = MAX_MONEY; - return nMinFee; } @@ -1186,9 +1191,11 @@ public: CBigNum GetBlockWork() const { - if (CBigNum().SetCompact(nBits) <= 0) + CBigNum bnTarget; + bnTarget.SetCompact(nBits); + if (bnTarget <= 0) return 0; - return (CBigNum(1)<<256) / (CBigNum().SetCompact(nBits)+1); + return (CBigNum(1)<<256) / (bnTarget+1); } bool IsInMainChain() const @@ -1470,10 +1477,10 @@ public: //// todo: add something to note what created it (user, getnewaddress, change) //// maybe should have a map property map - CWalletKey(int64 nTimeExpiresIn=0) + CWalletKey(int64 nExpires=0) { - nTimeCreated = (nTimeExpiresIn ? GetTime() : 0); - nTimeExpires = nTimeExpiresIn; + nTimeCreated = (nExpires ? GetTime() : 0); + nTimeExpires = nExpires; } IMPLEMENT_SERIALIZE diff --git a/serialize.h b/serialize.h index a88e312c8c7..792b9096dbe 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 = ".7"; +static const char* pszSubVer = ".8";