diff options
Diffstat (limited to 'src')
64 files changed, 519 insertions, 141 deletions
diff --git a/src/alert.cpp b/src/alert.cpp index f9cd58d38b..4dd3716e80 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 31aa0dc9e9..5e6566a7ac 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/core.cpp b/src/core.cpp index 57e72489a1..f5c460761e 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/db.cpp b/src/db.cpp index 51c28cda69..592512c947 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/init.cpp b/src/init.cpp index 12fb129073..9ba77105b4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -270,6 +270,7 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n"; strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n"; + strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n"; strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n"; strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + "\n"; strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + "\n"; @@ -337,6 +338,8 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles) LogPrintf("Importing bootstrap.dat...\n"); LoadExternalBlockFile(file); RenameOver(pathBootstrap, pathBootstrapOld); + } else { + LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string()); } } @@ -345,8 +348,10 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles) FILE *file = fopen(path.string().c_str(), "rb"); if (file) { CImportingNow imp; - LogPrintf("Importing %s...\n", path.string()); + LogPrintf("Importing blocks file %s...\n", path.string()); LoadExternalBlockFile(file); + } else { + LogPrintf("Warning: Could not open blocks file %s\n", path.string()); } } } @@ -454,6 +459,12 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("AppInit2 : parameter interaction: -salvagewallet=1 -> setting -rescan=1\n"); } + // -zapwallettx implies a rescan + if (GetBoolArg("-zapwallettxes", false)) { + if (SoftSetBoolArg("-rescan", true)) + LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=1 -> setting -rescan=1\n"); + } + // Make sure enough file descriptors are available int nBind = std::max((int)mapArgs.count("-bind"), 1); nMaxConnections = GetArg("-maxconnections", 125); @@ -899,6 +910,20 @@ bool AppInit2(boost::thread_group& threadGroup) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { + if (GetBoolArg("-zapwallettxes", false)) { + uiInterface.InitMessage(_("Zapping all transactions from wallet...")); + + pwalletMain = new CWallet(strWalletFile); + DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(); + if (nZapWalletRet != DB_LOAD_OK) { + uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted")); + return false; + } + + delete pwalletMain; + pwalletMain = NULL; + } + uiInterface.InitMessage(_("Loading wallet...")); nStart = GetTimeMillis(); diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp index c2935ed017..43c737a599 100644 --- a/src/leveldbwrapper.cpp +++ b/src/leveldbwrapper.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2013 The Bitcoin developers +// Copyright (c) 2012-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/main.cpp b/src/main.cpp index d9cd23ce73..8e879c3169 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -872,7 +872,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } -int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const +int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const { if (hashBlock == 0 || nIndex == -1) return 0; @@ -897,6 +897,14 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const return chainActive.Height() - pindex->nHeight + 1; } +int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const +{ + int nResult = GetDepthInMainChainINTERNAL(pindexRet); + if (nResult == 0 && !mempool.exists(GetHash())) + return -1; // Not in chain, not in mempool + + return nResult; +} int CMerkleTx::GetBlocksToMaturity() const { diff --git a/src/main.h b/src/main.h index 05210e5164..781562854f 100644 --- a/src/main.h +++ b/src/main.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -77,12 +77,6 @@ static const unsigned char REJECT_CHECKPOINT = 0x43; extern CScript COINBASE_FLAGS; - - - - - - extern CCriticalSection cs_main; extern CTxMemPool mempool; extern std::map<uint256, CBlockIndex*> mapBlockIndex; @@ -96,7 +90,6 @@ extern bool fBenchmark; extern int nScriptCheckThreads; extern bool fTxIndex; extern unsigned int nCoinCacheSize; -extern bool fHaveGUI; // Minimum disk space required - used in CheckDiskSpace() static const uint64_t nMinDiskSpace = 52428800; @@ -423,6 +416,8 @@ public: /** A transaction with a merkle branch linking it to the block chain. */ class CMerkleTx : public CTransaction { +private: + int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const; public: uint256 hashBlock; std::vector<uint256> vMerkleBranch; @@ -461,9 +456,14 @@ public: int SetMerkleBranch(const CBlock* pblock=NULL); + + // Return depth of transaction in blockchain: + // -1 : not in blockchain, and not in memory pool (conflicted transaction) + // 0 : in memory pool, waiting to be included in a block + // >=1 : this many blocks deep in the main chain int GetDepthInMainChain(CBlockIndex* &pindexRet) const; int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } - bool IsInMainChain() const { return GetDepthInMainChain() > 0; } + bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; } int GetBlocksToMaturity() const; bool AcceptToMemoryPool(bool fLimitFree=true); }; diff --git a/src/miner.cpp b/src/miner.cpp index f9dab4bd67..73dd0a749d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/net.cpp b/src/net.cpp index 3d967004c5..359e629295 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/netbase.cpp b/src/netbase.cpp index 5ec760be38..d5b75d6afd 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/noui.cpp b/src/noui.cpp index f176e0eb59..32c861b0d9 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/protocol.cpp b/src/protocol.cpp index cc98e7e40c..c77a92f020 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 7de47291cc..030804db6e 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -243,6 +243,7 @@ RES_ICONS = \ res/icons/toolbar_testnet.png \ res/icons/transaction0.png \ res/icons/transaction2.png \ + res/icons/transaction_conflicted.png \ res/icons/tx_inout.png \ res/icons/tx_input.png \ res/icons/tx_output.png \ diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index dda79e3d0e..162009f5de 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 746b5a4092..7c3a7756b7 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -12,6 +12,7 @@ <file alias="connect_4">res/icons/connect4_16.png</file> <file alias="transaction_0">res/icons/transaction0.png</file> <file alias="transaction_confirmed">res/icons/transaction2.png</file> + <file alias="transaction_conflicted">res/icons/transaction_conflicted.png</file> <file alias="transaction_1">res/icons/clock1.png</file> <file alias="transaction_2">res/icons/clock2.png</file> <file alias="transaction_3">res/icons/clock3.png</file> diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index c1f2f18d45..25ad0c66af 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,12 +19,12 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) : amount(0), currentUnit(-1) { + nSingleStep = 100000; // satoshis + amount = new QDoubleSpinBox(this); amount->setLocale(QLocale::c()); - amount->setDecimals(8); amount->installEventFilter(this); amount->setMaximumWidth(170); - amount->setSingleStep(0.001); QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(amount); @@ -159,11 +159,7 @@ void BitcoinAmountField::unitChanged(int idx) // Set max length after retrieving the value, to prevent truncation amount->setDecimals(BitcoinUnits::decimals(currentUnit)); amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals())); - - if (currentUnit == BitcoinUnits::uBTC) - amount->setSingleStep(0.01); - else - amount->setSingleStep(0.001); + amount->setSingleStep((double)nSingleStep / (double)BitcoinUnits::factor(currentUnit)); if (valid) { @@ -182,3 +178,9 @@ void BitcoinAmountField::setDisplayUnit(int newUnit) { unit->setValue(newUnit); } + +void BitcoinAmountField::setSingleStep(qint64 step) +{ + nSingleStep = step; + unitChanged(unit->currentIndex()); +} diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index d54f536b1f..521a9ed561 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -26,6 +26,9 @@ public: qint64 value(bool *valid=0) const; void setValue(qint64 value); + /** Set single step in satoshis **/ + void setSingleStep(qint64 step); + /** Make read-only **/ void setReadOnly(bool fReadOnly); @@ -56,6 +59,7 @@ private: QDoubleSpinBox *amount; QValueComboBox *unit; int currentUnit; + qint64 nSingleStep; void setText(const QString &text); QString text() const; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index f548c65161..f66fab496c 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 4dce4431ba..0cc1ebc502 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index e0d99aac39..b4a9f1f580 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -28,52 +28,6 @@ </attribute> <layout class="QVBoxLayout" name="verticalLayout_Main"> <item> - <widget class="QLabel" name="transactionFeeInfoLabel"> - <property name="text"> - <string>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_1_Main"> - <item> - <widget class="QLabel" name="transactionFeeLabel"> - <property name="text"> - <string>Pay transaction &fee</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="buddy"> - <cstring>transactionFee</cstring> - </property> - </widget> - </item> - <item> - <widget class="BitcoinAmountField" name="transactionFee"/> - </item> - <item> - <spacer name="horizontalSpacer_1_Main"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> <widget class="QCheckBox" name="bitcoinAtStartup"> <property name="toolTip"> <string>Automatically start Bitcoin after logging in to the system.</string> @@ -194,6 +148,89 @@ </item> </layout> </widget> + <widget class="QWidget" name="tabWallet"> + <attribute name="title"> + <string>W&allet</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_Network"> + <item> + <widget class="QLabel" name="transactionFeeInfoLabel"> + <property name="text"> + <string>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_1_Main"> + <item> + <widget class="QLabel" name="transactionFeeLabel"> + <property name="text"> + <string>Pay transaction &fee</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="buddy"> + <cstring>transactionFee</cstring> + </property> + </widget> + </item> + <item> + <widget class="BitcoinAmountField" name="transactionFee"/> + </item> + <item> + <spacer name="horizontalSpacer_1_Main"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="spendZeroConfChange"> + <property name="text"> + <string>Spend unconfirmed change (experts only)</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> <widget class="QWidget" name="tabNetwork"> <attribute name="title"> <string>&Network</string> diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index d1a601706b..9f6588bc9e 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 453bbdf374..fc1258827e 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index f61bb3ed2c..f4eb7ef07e 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -15,6 +15,7 @@ #include "optionsmodel.h" #include "netbase.h" +#include "main.h" #include <QDir> #include <QIntValidator> @@ -93,6 +94,7 @@ OptionsDialog::OptionsDialog(QWidget *parent) : } ui->unit->setModel(new BitcoinUnits(this)); + ui->transactionFee->setSingleStep(CTransaction::nMinTxFee); /* Widget-to-option mapper */ mapper = new MonitoredDataMapper(this); @@ -148,11 +150,14 @@ void OptionsDialog::setModel(OptionsModel *model) void OptionsDialog::setMapper() { /* Main */ - mapper->addMapping(ui->transactionFee, OptionsModel::Fee); mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup); mapper->addMapping(ui->threadsScriptVerif, OptionsModel::ThreadsScriptVerif); mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); + /* Wallet */ + mapper->addMapping(ui->transactionFee, OptionsModel::Fee); + mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange); + /* Network */ mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index a2a2732b1c..eff73b7702 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -76,6 +76,11 @@ void OptionsModel::Init() nTransactionFee = settings.value("nTransactionFee").toLongLong(); // if -paytxfee is set, this will be overridden later in init.cpp if (mapArgs.count("-paytxfee")) strOverriddenByCommandLine += "-paytxfee "; + + if (!settings.contains("bSpendZeroConfChange")) + settings.setValue("bSpendZeroConfChange", true); + if (!SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool())) + strOverriddenByCommandLine += "-spendzeroconfchange "; #endif if (!settings.contains("nDatabaseCache")) @@ -184,6 +189,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const // Todo: Consider to revert back to use just nTransactionFee here, if we don't want // -paytxfee to update our QSettings! return settings.value("nTransactionFee"); + case SpendZeroConfChange: + return settings.value("bSpendZeroConfChange"); #endif case DisplayUnit: return nDisplayUnit; @@ -274,6 +281,12 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in settings.setValue("nTransactionFee", (qint64)nTransactionFee); emit transactionFeeChanged(nTransactionFee); break; + case SpendZeroConfChange: + if (settings.value("bSpendZeroConfChange") != value) { + settings.setValue("bSpendZeroConfChange", value); + setRestartRequired(true); + } + break; #endif case DisplayUnit: nDisplayUnit = value.toInt(); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index e5c1e3e8b9..a3487ddd2e 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -40,6 +40,7 @@ public: CoinControlFeatures, // bool ThreadsScriptVerif, // int DatabaseCache, // int + SpendZeroConfChange, // bool OptionIDRowCount, }; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 016097c5a0..1a9d1de571 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -175,6 +175,7 @@ void OverviewPage::setWalletModel(WalletModel *model) filter->setLimit(NUM_ITEMS); filter->setDynamicSortFilter(true); filter->setSortRole(Qt::EditRole); + filter->setShowInactive(false); filter->sort(TransactionTableModel::Status, Qt::DescendingOrder); ui->listTransactions->setModel(filter); diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index af19661bdd..d84d09c57d 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 8ef80d32ea..7539645b47 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 2c6de0cbca..12d2235782 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 64f140bc86..844d62518c 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 6fed208345..d4cc5078aa 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/res/icons/transaction_conflicted.png b/src/qt/res/icons/transaction_conflicted.png Binary files differnew file mode 100644 index 0000000000..51fff649ab --- /dev/null +++ b/src/qt/res/icons/transaction_conflicted.png diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b1671b8a0e..bd29efee86 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 0cfd1c80d1..e5da01546a 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index c3a4e4a0db..33621e54b0 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index c21679ea8a..cacf5dc49b 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 6bc10e60ab..d79038d81d 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index c76b29861d..4aebaa1e7f 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -30,7 +30,9 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) else { int nDepth = wtx.GetDepthInMainChain(); - if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (nDepth < 0) + return tr("conflicted"); + else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index a14e74a469..f9546fddb5 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -5,6 +5,7 @@ #include "transactionfilterproxy.h" #include "transactiontablemodel.h" +#include "transactionrecord.h" #include <cstdlib> @@ -22,7 +23,8 @@ TransactionFilterProxy::TransactionFilterProxy(QObject *parent) : addrPrefix(), typeFilter(ALL_TYPES), minAmount(0), - limitRows(-1) + limitRows(-1), + showInactive(true) { } @@ -35,7 +37,10 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & QString address = index.data(TransactionTableModel::AddressRole).toString(); QString label = index.data(TransactionTableModel::LabelRole).toString(); qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); + int status = index.data(TransactionTableModel::StatusRole).toInt(); + if(!showInactive && status == TransactionStatus::Conflicted) + return false; if(!(TYPE(type) & typeFilter)) return false; if(datetime < dateFrom || datetime > dateTo) @@ -78,6 +83,12 @@ void TransactionFilterProxy::setLimit(int limit) this->limitRows = limit; } +void TransactionFilterProxy::setShowInactive(bool showInactive) +{ + this->showInactive = showInactive; + invalidateFilter(); +} + int TransactionFilterProxy::rowCount(const QModelIndex &parent) const { if(limitRows != -1) diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index 6d1644d48d..9919bc3fd6 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -36,6 +36,9 @@ public: /** Set maximum number of rows returned, -1 if unlimited. */ void setLimit(int limit); + /** Set whether to show conflicted transactions. */ + void setShowInactive(bool showInactive); + int rowCount(const QModelIndex &parent = QModelIndex()) const; protected: @@ -48,6 +51,7 @@ private: quint32 typeFilter; qint64 minAmount; int limitRows; + bool showInactive; }; #endif // TRANSACTIONFILTERPROXY_H diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 257151b926..8cfaed27c7 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -164,7 +164,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) (wtx.IsCoinBase() ? 1 : 0), wtx.nTimeReceived, idx); - status.confirmed = wtx.IsConfirmed(); + status.confirmed = wtx.IsTrusted(); status.depth = wtx.GetDepthInMainChain(); status.cur_num_blocks = chainActive.Height(); @@ -183,7 +183,11 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) } else { - if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + if (status.depth < 0) + { + status.status = TransactionStatus::Conflicted; + } + else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) { status.status = TransactionStatus::Offline; } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 8a7c9044e3..d7be0bc438 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -36,7 +36,8 @@ public: OpenUntilBlock, Offline, Unconfirmed, - HaveConfirmations + HaveConfirmations, + Conflicted }; bool confirmed; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index b29be7e0cb..7d76204ba4 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -312,7 +312,7 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for)); break; case TransactionStatus::Offline: - status = tr("Offline (%1 confirmations)").arg(wtx->status.depth); + status = tr("Offline"); break; case TransactionStatus::Unconfirmed: status = tr("Unconfirmed (%1 of %2 confirmations)").arg(wtx->status.depth).arg(TransactionRecord::NumConfirmations); @@ -320,6 +320,9 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons case TransactionStatus::HaveConfirmations: status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth); break; + case TransactionStatus::Conflicted: + status = tr("Conflicted"); + break; } } @@ -471,7 +474,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) case TransactionStatus::OpenUntilBlock: case TransactionStatus::OpenUntilDate: return QColor(64,64,255); - break; case TransactionStatus::Offline: return QColor(192,192,192); case TransactionStatus::Unconfirmed: @@ -486,6 +488,8 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) }; case TransactionStatus::HaveConfirmations: return QIcon(":/icons/transaction_confirmed"); + case TransactionStatus::Conflicted: + return QIcon(":/icons/transaction_conflicted"); } } return QColor(0,0,0); @@ -587,6 +591,8 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const rec->status.maturity != TransactionStatus::Mature); case FormattedAmountRole: return formatTxAmount(rec, false); + case StatusRole: + return rec->status.status; } return QVariant(); } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index c23c606c31..7b9cf09cbe 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -53,7 +53,9 @@ public: /** Is transaction confirmed? */ ConfirmedRole, /** Formatted amount, without brackets when unconfirmed */ - FormattedAmountRole + FormattedAmountRole, + /** Transaction status (TransactionRecord::Status) */ + StatusRole }; int rowCount(const QModelIndex &parent) const; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ddc8c6ea79..3549cd49f0 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -494,7 +494,9 @@ void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vect BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) { if (!wallet->mapWallet.count(outpoint.hash)) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, wallet->mapWallet[outpoint.hash].GetDepthInMainChain()); + int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); + if (nDepth < 0) continue; + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); vOutputs.push_back(out); } } @@ -513,7 +515,9 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins) { if (!wallet->mapWallet.count(outpoint.hash)) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, wallet->mapWallet[outpoint.hash].GetDepthInMainChain()); + int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); + if (nDepth < 0) continue; + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); vCoins.push_back(out); } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 6d9d866b25..91a6fba222 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2013 The Bitcoin developers +// Copyright (c) 2011-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index f66dbc0eb0..a912ea7670 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 1d3237dfc1..353fb77b88 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index d9bcc3429d..b764349338 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 0632bdae6f..4ea84e99be 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index d3ed48525f..80cdb34f15 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index ff652ca34d..e2bdc80aef 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index ef43ecdeb1..4d110124b2 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcserver.h b/src/rpcserver.h index 9008c32810..0dd583c8eb 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 7045225825..c9152d7759 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -45,13 +45,18 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) entry.push_back(Pair("confirmations", confirms)); if (wtx.IsCoinBase()) entry.push_back(Pair("generated", true)); - if (confirms) + if (confirms > 0) { entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); entry.push_back(Pair("blockindex", wtx.nIndex)); entry.push_back(Pair("blocktime", (boost::int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); } - entry.push_back(Pair("txid", wtx.GetHash().GetHex())); + uint256 hash = wtx.GetHash(); + entry.push_back(Pair("txid", hash.GetHex())); + Array conflicts; + BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) + conflicts.push_back(conflict.GetHex()); + entry.push_back(Pair("walletconflicts", conflicts)); entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime())); entry.push_back(Pair("timereceived", (boost::int64_t)wtx.nTimeReceived)); BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue) @@ -621,7 +626,7 @@ Value getbalance(const Array& params, bool fHelp) for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (!wtx.IsConfirmed()) + if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0) continue; int64_t allFee; @@ -1109,7 +1114,10 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe Object entry; entry.push_back(Pair("account", strSentAccount)); MaybePushAddress(entry, s.first); - entry.push_back(Pair("category", "send")); + if (wtx.GetDepthInMainChain() < 0) + entry.push_back(Pair("category", "conflicted")); + else + entry.push_back(Pair("category", "send")); entry.push_back(Pair("amount", ValueFromAmount(-s.second))); entry.push_back(Pair("fee", ValueFromAmount(-nFee))); if (fLong) @@ -1141,7 +1149,12 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe entry.push_back(Pair("category", "generate")); } else - entry.push_back(Pair("category", "receive")); + { + if (wtx.GetDepthInMainChain() < 0) + entry.push_back(Pair("category", "conflicted")); + else + entry.push_back(Pair("category", "receive")); + } entry.push_back(Pair("amount", ValueFromAmount(r.second))); if (fLong) WalletTxToJSON(wtx, entry); @@ -1317,6 +1330,8 @@ Value listaccounts(const Array& params, bool fHelp) string strSentAccount; list<pair<CTxDestination, int64_t> > listReceived; list<pair<CTxDestination, int64_t> > listSent; + if (wtx.GetBlocksToMaturity() > 0) + continue; wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); mapAccountBalances[strSentAccount] -= nFee; BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) @@ -1448,7 +1463,8 @@ Value gettransaction(const Array& params, bool fHelp) " \"amount\" : x.xxx (numeric) The amount in btc\n" " }\n" " ,...\n" - " ]\n" + " ],\n" + " \"hex\" : \"data\" (string) Raw data for transaction\n" "}\n" "\nbExamples\n" @@ -1479,6 +1495,11 @@ Value gettransaction(const Array& params, bool fHelp) ListTransactions(wtx, "*", 0, false, details); entry.push_back(Pair("details", details)); + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << wtx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + entry.push_back(Pair("hex", strHex)); + return entry; } diff --git a/src/txdb.cpp b/src/txdb.cpp index bd6dae0f6e..d06639a112 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/util.cpp b/src/util.cpp index 7d748ac3bf..8cfd1c2e03 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/util.h b/src/util.h index d2bb8a4afc..6f7627e090 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet.cpp b/src/wallet.cpp index 0e51ebb448..823c96949f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -231,6 +231,82 @@ bool CWallet::SetMaxVersion(int nVersion) return true; } +set<uint256> CWallet::GetConflicts(const uint256& txid) const +{ + set<uint256> result; + AssertLockHeld(cs_wallet); + + std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid); + if (it == mapWallet.end()) + return result; + const CWalletTx& wtx = it->second; + + std::pair<TxConflicts::const_iterator, TxConflicts::const_iterator> range; + + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + { + range = mapTxConflicts.equal_range(txin.prevout); + for (TxConflicts::const_iterator it = range.first; it != range.second; ++it) + result.insert(it->second); + } + return result; +} + +void CWallet::SyncMetaData(pair<TxConflicts::iterator, TxConflicts::iterator> range) +{ + // We want all the wallet transactions in range to have the same metadata as + // the oldest (smallest nOrderPos). + // So: find smallest nOrderPos: + + int nMinOrderPos = std::numeric_limits<int>::max(); + const CWalletTx* copyFrom = NULL; + for (TxConflicts::iterator it = range.first; it != range.second; ++it) + { + const uint256& hash = it->second; + int n = mapWallet[hash].nOrderPos; + if (n < nMinOrderPos) + { + nMinOrderPos = n; + copyFrom = &mapWallet[hash]; + } + } + // Now copy data from copyFrom to rest: + for (TxConflicts::iterator it = range.first; it != range.second; ++it) + { + const uint256& hash = it->second; + CWalletTx* copyTo = &mapWallet[hash]; + if (copyFrom == copyTo) continue; + copyTo->mapValue = copyFrom->mapValue; + copyTo->vOrderForm = copyFrom->vOrderForm; + // fTimeReceivedIsTxTime not copied on purpose + // nTimeReceived not copied on purpose + copyTo->nTimeSmart = copyFrom->nTimeSmart; + copyTo->fFromMe = copyFrom->fFromMe; + copyTo->strFromAccount = copyFrom->strFromAccount; + // vfSpent not copied on purpose + // nOrderPos not copied on purpose + // cached members not copied on purpose + } +} + +void CWallet::AddToConflicts(const uint256& wtxhash) +{ + assert(mapWallet.count(wtxhash)); + CWalletTx& thisTx = mapWallet[wtxhash]; + if (thisTx.IsCoinBase()) + return; + + BOOST_FOREACH(const CTxIn& txin, thisTx.vin) + { + mapTxConflicts.insert(make_pair(txin.prevout, wtxhash)); + + pair<TxConflicts::iterator, TxConflicts::iterator> range; + range = mapTxConflicts.equal_range(txin.prevout); + if (range.first != range.second) + SyncMetaData(range); + } +} + bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) { if (IsCrypted()) @@ -385,9 +461,16 @@ void CWallet::MarkDirty() } } -bool CWallet::AddToWallet(const CWalletTx& wtxIn) +bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) { uint256 hash = wtxIn.GetHash(); + + if (fFromLoadWallet) + { + mapWallet[hash] = wtxIn; + AddToConflicts(hash); + } + else { LOCK(cs_wallet); // Inserts only if not already there, returns tx inserted or tx found @@ -445,6 +528,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) wtxIn.GetHash().ToString(), wtxIn.hashBlock.ToString()); } + AddToConflicts(hash); } bool fUpdated = false; @@ -907,6 +991,18 @@ void CWalletTx::RelayWalletTransaction() } } +set<uint256> CWalletTx::GetConflicts() const +{ + set<uint256> result; + if (pwallet != NULL) + { + uint256 myHash = GetHash(); + result = pwallet->GetConflicts(myHash); + result.erase(myHash); + } + return result; +} + void CWallet::ResendWalletTransactions() { // Do this infrequently and randomly to avoid giving away @@ -964,7 +1060,7 @@ int64_t CWallet::GetBalance() const for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (pcoin->IsConfirmed()) + if (pcoin->IsTrusted()) nTotal += pcoin->GetAvailableCredit(); } } @@ -980,7 +1076,7 @@ int64_t CWallet::GetUnconfirmedBalance() const for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed()) + if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) nTotal += pcoin->GetAvailableCredit(); } } @@ -1015,17 +1111,21 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const if (!IsFinalTx(*pcoin)) continue; - if (fOnlyConfirmed && !pcoin->IsConfirmed()) + if (fOnlyConfirmed && !pcoin->IsTrusted()) continue; if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) continue; + int nDepth = pcoin->GetDepthInMainChain(); + if (nDepth < 0) + continue; + for (unsigned int i = 0; i < pcoin->vout.size(); i++) { if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain())); + vCoins.push_back(COutput(pcoin, i, nDepth)); } } } @@ -1497,6 +1597,30 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) } +DBErrors CWallet::ZapWalletTx() +{ + if (!fFileBacked) + return DB_LOAD_OK; + DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this); + if (nZapWalletTxRet == DB_NEED_REWRITE) + { + if (CDB::Rewrite(strWalletFile, "\x04pool")) + { + LOCK(cs_wallet); + setKeyPool.clear(); + // Note: can't top-up keypool here, because wallet is locked. + // User will be prompted to unlock wallet the next operation + // the requires a new key. + } + } + + if (nZapWalletTxRet != DB_LOAD_OK) + return nZapWalletTxRet; + + return DB_LOAD_OK; +} + + bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose) { AssertLockHeld(cs_wallet); // mapAddressBook @@ -1710,7 +1834,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances() { CWalletTx *pcoin = &walletEntry.second; - if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed()) + if (!IsFinalTx(*pcoin) || !pcoin->IsTrusted()) continue; if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) diff --git a/src/wallet.h b/src/wallet.h index e5104f1362..95fb0ee9de 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -108,6 +108,12 @@ private: int64_t nNextResend; int64_t nLastResend; + // Used to detect and report conflicted transactions: + typedef std::multimap<COutPoint, uint256> TxConflicts; + TxConflicts mapTxConflicts; + void AddToConflicts(const uint256& wtxhash); + void SyncMetaData(std::pair<TxConflicts::iterator, TxConflicts::iterator>); + public: /// Main wallet lock. /// This lock protects all the fields added by CWallet @@ -151,6 +157,7 @@ public: } std::map<uint256, CWalletTx> mapWallet; + int64_t nOrderPosNext; std::map<uint256, int> mapRequestCount; @@ -223,7 +230,7 @@ public: TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = ""); void MarkDirty(); - bool AddToWallet(const CWalletTx& wtxIn); + bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false); void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256 &hash); @@ -323,6 +330,7 @@ public: void SetBestChain(const CBlockLocator& loc); DBErrors LoadWallet(bool& fFirstRunRet); + DBErrors ZapWalletTx(); bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose); @@ -357,6 +365,9 @@ public: // get the current wallet format (the oldest client version guaranteed to understand this wallet) int GetVersion() { AssertLockHeld(cs_wallet); return nWalletVersion; } + // Get wallet transactions that conflict with given transaction (spend same outputs) + std::set<uint256> GetConflicts(const uint256& txid) const; + /** Address book entry changed. * @note called with lock cs_wallet held. */ @@ -695,13 +706,16 @@ public: return (GetDebit() > 0); } - bool IsConfirmed() const + bool IsTrusted() const { // Quick answer in most cases if (!IsFinalTx(*this)) return false; - if (GetDepthInMainChain() >= 1) + int nDepth = GetDepthInMainChain(); + if (nDepth >= 1) return true; + if (nDepth < 0) + return false; if (!bSpendZeroConfChange || !IsFromMe()) // using wtx's cached debit return false; @@ -717,8 +731,11 @@ public: if (!IsFinalTx(*ptx)) return false; - if (ptx->GetDepthInMainChain() >= 1) + int nPDepth = ptx->GetDepthInMainChain(); + if (nPDepth >= 1) continue; + if (nPDepth < 0) + return false; if (!pwallet->IsFromMe(*ptx)) return false; @@ -746,6 +763,8 @@ public: void AddSupportingTransactions(); bool AcceptWalletTransaction(); void RelayWalletTransaction(); + + std::set<uint256> GetConflicts() const; }; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 56349fcfbd..b3816a54b6 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -382,7 +382,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, if (wtx.nOrderPos == -1) wss.fAnyUnordered = true; - pwallet->mapWallet[hash] = wtx; + pwallet->AddToWallet(wtx, true); //// debug print //LogPrintf("LoadWallet %s\n", wtx.GetHash().ToString()); //LogPrintf(" %12"PRId64" %s %s %s\n", @@ -684,6 +684,86 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return result; } +DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash) +{ + pwallet->vchDefaultKey = CPubKey(); + CWalletScanState wss; + bool fNoncriticalErrors = false; + DBErrors result = DB_LOAD_OK; + + try { + LOCK(pwallet->cs_wallet); + int nMinVersion = 0; + if (Read((string)"minversion", nMinVersion)) + { + if (nMinVersion > CLIENT_VERSION) + return DB_TOO_NEW; + pwallet->LoadMinVersion(nMinVersion); + } + + // Get cursor + Dbc* pcursor = GetCursor(); + if (!pcursor) + { + LogPrintf("Error getting wallet database cursor\n"); + return DB_CORRUPT; + } + + while (true) + { + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue); + if (ret == DB_NOTFOUND) + break; + else if (ret != 0) + { + LogPrintf("Error reading next record from wallet database\n"); + return DB_CORRUPT; + } + + string strType; + ssKey >> strType; + if (strType == "tx") { + uint256 hash; + ssKey >> hash; + + vTxHash.push_back(hash); + } + } + pcursor->close(); + } + catch (boost::thread_interrupted) { + throw; + } + catch (...) { + result = DB_CORRUPT; + } + + if (fNoncriticalErrors && result == DB_LOAD_OK) + result = DB_NONCRITICAL_ERROR; + + return result; +} + +DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet) +{ + // build list of wallet TXs + vector<uint256> vTxHash; + DBErrors err = FindWalletTx(pwallet, vTxHash); + if (err != DB_LOAD_OK) + return err; + + // erase each wallet TX + BOOST_FOREACH (uint256& hash, vTxHash) { + if (!EraseTx(hash)) + return DB_CORRUPT; + } + + return DB_LOAD_OK; +} + void ThreadFlushWalletDB(const string& strFile) { // Make this thread recognisable as the wallet flushing thread diff --git a/src/walletdb.h b/src/walletdb.h index 4f3e29283e..3bfb436050 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -122,6 +122,8 @@ public: DBErrors ReorderTransactions(CWallet*); DBErrors LoadWallet(CWallet* pwallet); + DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash); + DBErrors ZapWalletTx(CWallet* pwallet); static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, std::string filename); }; |