Merge branch '0.5.0.x' into 0.5.x
authorLuke Dashjr <luke-jr+git@utopios.org>
Mon, 16 Apr 2012 01:06:10 +0000 (21:06 -0400)
committerLuke Dashjr <luke-jr+git@utopios.org>
Mon, 16 Apr 2012 01:06:10 +0000 (21:06 -0400)
21 files changed:
scripts/qt/extract_strings_qt.py
scripts/qt/make_windows_icon.py [changed from file to symlink]
scripts/qt/make_windows_icon.sh [new file with mode: 0755]
src/bignum.h
src/bitcoinrpc.cpp
src/keystore.h
src/main.cpp
src/main.h
src/qt/addresstablemodel.cpp
src/qt/bitcoin.cpp
src/qt/bitcoingui.cpp
src/qt/bitcoinstrings.cpp
src/qt/editaddressdialog.cpp
src/qt/optionsdialog.cpp
src/qt/sendcoinsdialog.cpp
src/qt/transactiontablemodel.cpp
src/qt/walletmodel.h
src/uint256.h
src/util.cpp
src/wallet.cpp
src/wallet.h

index 6627de4..b047869 100755 (executable)
@@ -53,9 +53,15 @@ child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE)
 messages = parse_po(out) 
 
 f = open(OUT_CPP, 'w')
-f.write('#include <QtGlobal>\n')
-f.write('// Automatically generated by extract_strings.py\n')
-f.write('static const char *bitcoin_strings[] = {')
+f.write("""#include <QtGlobal>
+// Automatically generated by extract_strings.py
+#ifdef __GNUC__
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+""")
+f.write('static const char UNUSED *bitcoin_strings[] = {')
 for (msgid, msgstr) in messages:
     if msgid != EMPTY:
         f.write('QT_TRANSLATE_NOOP("bitcoin-core", %s),\n' % ('\n'.join(msgid)))
deleted file mode 100755 (executable)
index bf607b1c62384eba8ddbe4acf9f930d1b0f03ae3..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-# create multiresolution windows icon
-ICON_SRC=../../src/qt/res/icons/bitcoin.png
-ICON_DST=../../src/qt/res/icons/bitcoin.ico
-convert ${ICON_SRC} -resize 16x16 bitcoin-16.png
-convert ${ICON_SRC} -resize 32x32 bitcoin-32.png
-convert ${ICON_SRC} -resize 48x48 bitcoin-48.png
-convert bitcoin-16.png bitcoin-32.png bitcoin-48.png ${ICON_DST}
-
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..f51c32a21584def1d46807d41a5255bc8f57476b
--- /dev/null
@@ -0,0 +1 @@
+make_windows_icon.sh
\ No newline at end of file
diff --git a/scripts/qt/make_windows_icon.sh b/scripts/qt/make_windows_icon.sh
new file mode 100755 (executable)
index 0000000..bf607b1
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+# create multiresolution windows icon
+ICON_SRC=../../src/qt/res/icons/bitcoin.png
+ICON_DST=../../src/qt/res/icons/bitcoin.ico
+convert ${ICON_SRC} -resize 16x16 bitcoin-16.png
+convert ${ICON_SRC} -resize 32x32 bitcoin-32.png
+convert ${ICON_SRC} -resize 48x48 bitcoin-48.png
+convert bitcoin-16.png bitcoin-32.png bitcoin-48.png ${ICON_DST}
+
index 6e8d3cb..641ebf4 100644 (file)
@@ -300,7 +300,7 @@ public:
         while (isxdigit(*psz))
         {
             *this <<= 4;
-            int n = phexdigit[*psz++];
+            int n = phexdigit[(unsigned char)*psz++];
             *this += n;
         }
         if (fNegative)
index f10de69..77efdfa 100644 (file)
@@ -753,8 +753,10 @@ Value getbalance(const Array& params, bool fHelp)
             list<pair<CBitcoinAddress, int64> > listSent;
             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
             if (wtx.GetDepthInMainChain() >= nMinDepth)
+            {
                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
                     nBalance += r.second;
+            }
             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
                 nBalance -= r.second;
             nBalance -= allFee;
@@ -1112,6 +1114,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
 
     // Received
     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+    {
         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
         {
             string account;
@@ -1129,6 +1132,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
                 ret.push_back(entry);
             }
         }
+    }
 }
 
 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
@@ -1165,14 +1169,21 @@ Value listtransactions(const Array& params, bool fHelp)
     if (params.size() > 2)
         nFrom = params[2].get_int();
 
+    if (nCount < 0)
+        throw JSONRPCError(-8, "Negative count");
+    if (nFrom < 0)
+        throw JSONRPCError(-8, "Negative from");
+
     Array ret;
     CWalletDB walletdb(pwalletMain->strWalletFile);
 
-    // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
+    // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
     typedef multimap<int64, TxPair > TxItems;
     TxItems txByTime;
 
+    // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
+    // would make this much faster for applications that do this a lot.
     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
     {
         CWalletTx* wtx = &((*it).second);
@@ -1185,10 +1196,8 @@ Value listtransactions(const Array& params, bool fHelp)
         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
     }
 
-    // Now: iterate backwards until we have nCount items to return:
-    TxItems::reverse_iterator it = txByTime.rbegin();
-    if (txByTime.size() > nFrom) std::advance(it, nFrom);
-    for (; it != txByTime.rend(); ++it)
+    // iterate backwards until we have nCount items to return:
+    for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
     {
         CWalletTx *const pwtx = (*it).second.first;
         if (pwtx != 0)
@@ -1197,18 +1206,21 @@ Value listtransactions(const Array& params, bool fHelp)
         if (pacentry != 0)
             AcentryToJSON(*pacentry, strAccount, ret);
 
-        if (ret.size() >= nCount) break;
+        if (ret.size() >= (nCount+nFrom)) break;
     }
-    // ret is now newest to oldest
+    // ret is newest to oldest
     
-    // Make sure we return only last nCount items (sends-to-self might give us an extra):
-    if (ret.size() > nCount)
-    {
-        Array::iterator last = ret.begin();
-        std::advance(last, nCount);
-        ret.erase(last, ret.end());
-    }
-    std::reverse(ret.begin(), ret.end()); // oldest to newest
+    if (nFrom > ret.size()) nFrom = ret.size();
+    if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
+    Array::iterator first = ret.begin();
+    std::advance(first, nFrom);
+    Array::iterator last = ret.begin();
+    std::advance(last, nFrom+nCount);
+
+    if (last != ret.end()) ret.erase(last, ret.end());
+    if (first != ret.begin()) ret.erase(ret.begin(), first);
+
+    std::reverse(ret.begin(), ret.end()); // Return oldest to newest
 
     return ret;
 }
@@ -2160,6 +2172,10 @@ void ThreadRPCServer(void* parg)
     printf("ThreadRPCServer exiting\n");
 }
 
+#ifdef QT_GUI
+extern bool HACK_SHUTDOWN;
+#endif
+
 void ThreadRPCServer2(void* parg)
 {
     printf("ThreadRPCServer started\n");
@@ -2196,9 +2212,27 @@ void ThreadRPCServer2(void* parg)
 
     asio::io_service io_service;
     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
+#ifndef QT_GUI
     ip::tcp::acceptor acceptor(io_service, endpoint);
 
     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+#else
+    ip::tcp::acceptor acceptor(io_service);
+    try
+    {
+        acceptor.open(endpoint.protocol());
+        acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+        acceptor.bind(endpoint);
+        acceptor.listen(socket_base::max_connections);
+    }
+    catch(system::system_error &e)
+    {
+        HACK_SHUTDOWN = true;
+        ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
+                             _("Error"), wxOK | wxMODAL);
+        return;
+    }
+#endif
 
 #ifdef USE_SSL
     ssl::context context(io_service, ssl::context::sslv23);
index 4d88914..8aaf3e6 100644 (file)
@@ -14,6 +14,8 @@ protected:
     mutable CCriticalSection cs_KeyStore;
 
 public:
+    virtual ~CKeyStore() {}
+
     // Add a key to the store.
     virtual bool AddKey(const CKey& key) =0;
 
index 3c5fef2..fade6a2 100644 (file)
@@ -1169,14 +1169,18 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
     // This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC.
     // On testnet it is enabled as of februari 20, 2012, 0:00 UTC.
     if (pindex->nTime > 1331769600 || (fTestNet && pindex->nTime > 1329696000))
+    {
         BOOST_FOREACH(CTransaction& tx, vtx)
         {
             CTxIndex txindexOld;
             if (txdb.ReadTxIndex(tx.GetHash(), txindexOld))
+            {
                 BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent)
                     if (pos.IsNull())
                         return false;
+            }
         }
+    }
 
     // P2SH didn't become active until Apr 1 2012 (Feb 15 on testnet)
     int64 nEvalSwitchTime = fTestNet ? 1329264000 : 1333238400;
index e400bd9..70d83b9 100644 (file)
@@ -578,9 +578,11 @@ public:
 
         // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
         if (nMinFee < nBaseFee)
+        {
             BOOST_FOREACH(const CTxOut& txout, vout)
                 if (txout.nValue < CENT)
                     nMinFee = nBaseFee;
+        }
 
         // Raise the price as the block approaches full
         if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
index 8fd6d52..5d724ea 100644 (file)
@@ -27,8 +27,9 @@ struct AddressTableEntry
 };
 
 // Private implementation
-struct AddressTablePriv
+class AddressTablePriv
 {
+public:
     CWallet *wallet;
     QList<AddressTableEntry> cachedAddressTable;
 
index 9ef7d5b..b7c8a45 100644 (file)
@@ -120,6 +120,15 @@ std::string _(const char* psz)
     return QCoreApplication::translate("bitcoin-core", psz).toStdString();
 }
 
+/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
+ */
+static void handleRunawayException(std::exception *e)
+{
+    PrintExceptionContinue(e, "Runaway exception");
+    QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occured. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
+    exit(1);
+}
+
 int main(int argc, char *argv[])
 {
     QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
@@ -205,9 +214,9 @@ int main(int argc, char *argv[])
             return 1;
         }
     } catch (std::exception& e) {
-        PrintException(&e, "Runaway exception");
+        handleRunawayException(&e);
     } catch (...) {
-        PrintException(NULL, "Runaway exception");
+        handleRunawayException(NULL);
     }
     return 0;
 }
index 0111ebb..778acd1 100644 (file)
@@ -4,6 +4,9 @@
  * W.J. van der Laan 2011
  * The Bitcoin Developers 2011
  */
+
+#include "checkpoints.h"
+
 #include "bitcoingui.h"
 #include "transactiontablemodel.h"
 #include "addressbookpage.h"
@@ -480,7 +483,7 @@ void BitcoinGUI::setNumBlocks(int count)
     }
 
     // Set icon state: spinning if catching up, tick otherwise
-    if(secs < 90*60)
+    if(secs < 90*60 && count >= Checkpoints::GetTotalBlocksEstimate())
     {
         tooltip = tr("Up to date") + QString(".\n") + tooltip;
         labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
@@ -516,12 +519,16 @@ void BitcoinGUI::refreshStatusBar()
     setNumBlocks(clientModel->getNumBlocks());
 }
 
+bool HACK_SHUTDOWN = false;
+
 void BitcoinGUI::error(const QString &title, const QString &message, bool modal)
 {
     // Report errors from network/worker thread
     if (modal)
     {
         QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok);
+        if (HACK_SHUTDOWN)
+            QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
     } else {
         notificator->notify(Notificator::Critical, title, message);
     }
index 1b0a676..2d77441 100644 (file)
@@ -1,6 +1,11 @@
 #include <QtGlobal>
 // Automatically generated by extract_strings.py
-static const char *bitcoin_strings[] = {QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"),
+#ifdef __GNUC__
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+static const char UNUSED *bitcoin_strings[] = {QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"),
 QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"),
 QT_TRANSLATE_NOOP("bitcoin-core", "Send command to -server or bitcoind\n"),
 QT_TRANSLATE_NOOP("bitcoin-core", "List commands\n"),
index 8cc3c85..cecb8ae 100644 (file)
@@ -106,6 +106,9 @@ void EditAddressDialog::accept()
                 tr("New key generation failed."),
                 QMessageBox::Ok, QMessageBox::Ok);
             return;
+        case AddressTableModel::OK:
+            // Failed with unknown reason. Just reject.
+            break;
         }
 
         return;
index 75fd4cc..0025337 100644 (file)
@@ -278,7 +278,8 @@ DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
 
     layout->addLayout(unit_hbox);
 
-    display_addresses = new QCheckBox(tr("Display addresses in transaction list"), this);
+    display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
+    display_addresses->setToolTip(tr("Whether to show Bitcoin addresses in the transaction list"));
     layout->addWidget(display_addresses);
 
     layout->addStretch();
index 6577615..4c58b38 100644 (file)
@@ -148,6 +148,8 @@ void SendCoinsDialog::on_sendButton_clicked()
             tr("Error: The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."),
             QMessageBox::Ok, QMessageBox::Ok);
         break;
+    case WalletModel::Aborted: // User aborted, nothing to do
+        break;
     case WalletModel::OK:
         accept();
         break;
index 480d4ac..28620bf 100644 (file)
@@ -45,8 +45,9 @@ struct TxLessThan
 };
 
 // Private implementation
-struct TransactionTablePriv
+class TransactionTablePriv
 {
+public:
     TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent):
             wallet(wallet),
             parent(parent)
index 89e8cdd..a129808 100644 (file)
@@ -34,8 +34,7 @@ public:
         DuplicateAddress,
         TransactionCreationFailed, // Error returned when wallet is still locked
         TransactionCommitFailed,
-        Aborted,
-        MiscError
+        Aborted
     };
 
     enum EncryptionStatus
index ae26334..07809e4 100644 (file)
@@ -315,7 +315,7 @@ public:
         // hex string to uint
         static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
         const char* pbegin = psz;
-        while (phexdigit[*psz] || *psz == '0')
+        while (phexdigit[(unsigned char)*psz] || *psz == '0')
             psz++;
         psz--;
         unsigned char* p1 = (unsigned char*)pn;
index f6c37a2..5b59ead 100644 (file)
@@ -4,6 +4,17 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 #include "headers.h"
 #include "strlcpy.h"
+
+// Work around clang compilation problem in Boost 1.46:
+// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
+// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
+//           http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
+namespace boost {
+    namespace program_options {
+        std::string to_internal(const std::string&);
+    }
+}
+
 #include <boost/program_options/detail/config_file.hpp>
 #include <boost/program_options/parsers.hpp>
 #include <boost/filesystem.hpp>
@@ -567,7 +578,7 @@ vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
 
     while (1)
     {
-         int dec = decode64_table[*p];
+         int dec = decode64_table[(unsigned char)*p];
          if (dec == -1) break;
          p++;
          switch (mode)
@@ -607,12 +618,12 @@ vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
                 break;
 
             case 2: // 4n+2 base64 characters processed: require '=='
-                if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1)
+                if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
                     *pfInvalid = true;
                 break;
 
             case 3: // 4n+3 base64 characters processed: require '='
-                if (left || p[0] != '=' || decode64_table[p[1]] != -1)
+                if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
                     *pfInvalid = true;
                 break;
         }
index 20c3eab..43c9656 100644 (file)
@@ -547,8 +547,10 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
                 vtxPrev.push_back(tx);
 
                 if (nDepth < COPY_DEPTH)
+                {
                     BOOST_FOREACH(const CTxIn& txin, tx.vin)
                         vWorkQueue.push_back(txin.prevout.hash);
+                }
             }
         }
     }
index 62dd6d5..fe97a0a 100644 (file)
@@ -509,8 +509,10 @@ public:
                 return false;
 
             if (mapPrev.empty())
+            {
                 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
                     mapPrev[tx.GetHash()] = &tx;
+            }
 
             BOOST_FOREACH(const CTxIn& txin, ptx->vin)
             {