cleanup,
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Tue, 7 Sep 2010 01:12:53 +0000 (01:12 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Tue, 7 Sep 2010 01:12:53 +0000 (01:12 +0000)
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

18 files changed:
cryptopp/secblock.h
db.cpp
init.cpp
irc.cpp
main.cpp
main.h
makefile.unix
net.cpp
net.h
script.cpp
script.h
serialize.h
setup.nsi
sha256.cpp
ui.cpp
ui.h
util.cpp
util.h

index d66470e..5e38829 100644 (file)
@@ -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 56ec9ee..6b3af25 100644 (file)
--- 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;
index af8ad75..43a672f 100644 (file)
--- 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 daa9a0d..a520173 100644 (file)
--- 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());
@@ -158,6 +162,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;
     if (mapArgs.count("-noirc"))
@@ -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] != ':')
index 76d3037..835b7c7 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -91,7 +91,7 @@ vector<unsigned char> 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<uint256, CTxIndex>& 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<uint256, CNode*> mapMix;
                     foreach(CNode* pnode, vNodes)
                         mapMix.insert(make_pair(hashRand = Hash(BEGIN(hashRand), END(hashRand)), pnode));
-                    int nRelayNodes = 4;
+                    int nRelayNodes = 2;
                     for (multimap<uint256, CNode*>::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<uint256, CTxIndex> mapTestPool;
             vector<char> 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 0fb36eb..dd86fc1 100644 (file)
--- 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
     {
index 7a38bf0..2199415 100644 (file)
@@ -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 9aaa38f..d1fdd24 100644 (file)
--- a/net.cpp
+++ b/net.cpp
@@ -25,7 +25,6 @@ CNode* pnodeLocalHost = NULL;
 uint64 nLocalHostNonce = 0;
 array<int, 10> vnThreadsRunning;
 SOCKET hListenSocket = INVALID_SOCKET;
-int64 nThreadSocketHandlerHeartbeat = INT64_MAX;
 
 vector<CNode*> 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 e12a8e1..372e57f 100644 (file)
--- 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<int, 10> vnThreadsRunning;
 extern SOCKET hListenSocket;
-extern int64 nThreadSocketHandlerHeartbeat;
 
 extern vector<CNode*> vNodes;
 extern CCriticalSection cs_vNodes;
index 26c1f4a..9b30d5a 100644 (file)
@@ -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<valtype>& stack)
+{
+    if (stack.empty())
+        throw runtime_error("popstack() : stack empty");
+    stack.pop_back();
+}
+
 
 bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType)
 {
@@ -66,6 +73,8 @@ bool EvalScript(vector<vector<unsigned char> >& 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<bool> vfExec;
     vector<valtype> altstack;
     if (script.size() > 10000)
@@ -82,13 +91,11 @@ bool EvalScript(vector<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& 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<vector<unsigned char> >& stack, const CScript& script, co
     return true;
 }
 
-#undef top
-
 
 
 
@@ -945,10 +944,7 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> 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<pair<opcodetype, valtype> >& 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<pair<opcodetype, valtype> >& 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;
+            }
         }
     }
 
index 20d2931..c829ed0 100644 (file)
--- 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<unsigned char>& 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<vector<unsigned char> >& 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<unsigned char>& 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<unsigned char>& 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<unsigned char>& 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<unsigned char>* 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<unsigned char> 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<unsigned char> 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);
index e1404b7..5ded6bf 100644 (file)
@@ -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";
 
 
 
index 3dc1a15..78d83d4 100644 (file)
--- a/setup.nsi
+++ b/setup.nsi
@@ -7,7 +7,7 @@ RequestExecutionLevel highest
 \r
 # General Symbol Definitions\r
 !define REGKEY "SOFTWARE\$(^Name)"\r
-!define VERSION 0.3.10\r
+!define VERSION 0.3.12\r
 !define COMPANY "Bitcoin project"\r
 !define URL http://www.bitcoin.org/\r
 \r
@@ -42,12 +42,12 @@ Var StartMenuGroup
 !insertmacro MUI_LANGUAGE English\r
 \r
 # Installer attributes\r
-OutFile bitcoin-0.3.10-win32-setup.exe\r
+OutFile bitcoin-0.3.12-win32-setup.exe\r
 InstallDir $PROGRAMFILES\Bitcoin\r
 CRCCheck on\r
 XPStyle on\r
 ShowInstDetails show\r
-VIProductVersion 0.3.10.0\r
+VIProductVersion 0.3.12.0\r
 VIAddVersionKey ProductName Bitcoin\r
 VIAddVersionKey ProductVersion "${VERSION}"\r
 VIAddVersionKey CompanyName "${COMPANY}"\r
index 057f942..1bba8cf 100644 (file)
@@ -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 179b22d..4d4e846 100644 (file)
--- 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 b78f206..9769fd7 100644 (file)
--- 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);
     }
index 2a3e964..ef2e683 100644 (file)
--- 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 56b13c0..22ace61 100644 (file)
--- 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<string>& 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<typename T>
-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<unsigned char> vch, bool fSpaces=true)
+inline string HexStr(const vector<unsigned char>& 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<unsigned char>& vch, bool f0x=true)
+{
+    return HexNumStr(vch.begin(), vch.end(), f0x);
+}
+
 template<typename T>
 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<unsigned char> vch, const char* pszFormat="%s", bool fSpaces=true)
+inline void PrintHex(const vector<unsigned char>& 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)     \