aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.bench.include3
-rw-r--r--src/bench/base58.cpp56
-rw-r--r--src/bench/bench.cpp35
-rw-r--r--src/bench/bench.h7
-rw-r--r--src/bench/crypto_hash.cpp25
-rw-r--r--src/init.cpp26
-rw-r--r--src/key.cpp3
-rw-r--r--src/main.cpp33
-rw-r--r--src/net.cpp3
-rw-r--r--src/net.h1
-rw-r--r--src/qt/askpassphrasedialog.cpp21
-rw-r--r--src/qt/askpassphrasedialog.h1
-rw-r--r--src/qt/bitcoingui.cpp12
-rw-r--r--src/qt/bitcoingui.h1
-rw-r--r--src/qt/overviewpage.cpp2
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/qt/walletmodel.cpp2
-rw-r--r--src/random.cpp66
-rw-r--r--src/random.h11
-rw-r--r--src/rpc/net.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp2
-rw-r--r--src/test/sighash_tests.cpp1
-rw-r--r--src/wallet/rpcwallet.cpp40
-rw-r--r--src/wallet/wallet.cpp79
-rw-r--r--src/wallet/wallet.h4
-rw-r--r--src/wallet/walletdb.cpp40
-rw-r--r--src/wallet/walletdb.h1
28 files changed, 345 insertions, 137 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3c056386fa..f630ad4aa1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -374,7 +374,8 @@ endif
bitcoin_cli_LDADD = \
$(LIBBITCOIN_CLI) \
$(LIBUNIVALUE) \
- $(LIBBITCOIN_UTIL)
+ $(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_CRYPTO)
bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
#
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 65fd24e051..4067ceb399 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -9,7 +9,8 @@ bench_bench_bitcoin_SOURCES = \
bench/bench.h \
bench/Examples.cpp \
bench/rollingbloom.cpp \
- bench/crypto_hash.cpp
+ bench/crypto_hash.cpp \
+ bench/base58.cpp
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp
new file mode 100644
index 0000000000..1279c3e7df
--- /dev/null
+++ b/src/bench/base58.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2016 the Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "bench.h"
+
+#include "main.h"
+#include "base58.h"
+
+#include <vector>
+#include <string>
+
+
+static void Base58Encode(benchmark::State& state)
+{
+ unsigned char buff[32] = {
+ 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147,
+ 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90,
+ 200, 24
+ };
+ unsigned char* b = buff;
+ while (state.KeepRunning()) {
+ EncodeBase58(b, b + 32);
+ }
+}
+
+
+static void Base58CheckEncode(benchmark::State& state)
+{
+ unsigned char buff[32] = {
+ 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147,
+ 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90,
+ 200, 24
+ };
+ unsigned char* b = buff;
+ std::vector<unsigned char> vch;
+ vch.assign(b, b + 32);
+ while (state.KeepRunning()) {
+ EncodeBase58Check(vch);
+ }
+}
+
+
+static void Base58Decode(benchmark::State& state)
+{
+ const char* addr = "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem";
+ std::vector<unsigned char> vch;
+ while (state.KeepRunning()) {
+ DecodeBase58(addr, vch);
+ }
+}
+
+
+BENCHMARK(Base58Encode);
+BENCHMARK(Base58CheckEncode);
+BENCHMARK(Base58Decode);
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 6ee3cdc27a..227546a7a7 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -5,6 +5,7 @@
#include "bench.h"
#include <iostream>
+#include <iomanip>
#include <sys/time.h>
using namespace benchmark;
@@ -25,7 +26,7 @@ BenchRunner::BenchRunner(std::string name, BenchFunction func)
void
BenchRunner::RunAll(double elapsedTimeForOne)
{
- std::cout << "Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n";
+ std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n";
for (std::map<std::string,BenchFunction>::iterator it = benchmarks.begin();
it != benchmarks.end(); ++it) {
@@ -38,22 +39,34 @@ BenchRunner::RunAll(double elapsedTimeForOne)
bool State::KeepRunning()
{
+ if (count & countMask) {
+ ++count;
+ return true;
+ }
double now;
if (count == 0) {
- beginTime = now = gettimedouble();
+ lastTime = beginTime = now = gettimedouble();
}
else {
- // timeCheckCount is used to avoid calling gettime most of the time,
- // so benchmarks that run very quickly get consistent results.
- if ((count+1)%timeCheckCount != 0) {
- ++count;
- return true; // keep going
- }
now = gettimedouble();
- double elapsedOne = (now - lastTime)/timeCheckCount;
+ double elapsed = now - lastTime;
+ double elapsedOne = elapsed * countMaskInv;
if (elapsedOne < minTime) minTime = elapsedOne;
if (elapsedOne > maxTime) maxTime = elapsedOne;
- if (elapsedOne*timeCheckCount < maxElapsed/16) timeCheckCount *= 2;
+ if (elapsed*128 < maxElapsed) {
+ // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
+ // The restart avoids including the overhead of this code in the measurement.
+ countMask = ((countMask<<3)|7) & ((1LL<<60)-1);
+ countMaskInv = 1./(countMask+1);
+ count = 0;
+ minTime = std::numeric_limits<double>::max();
+ maxTime = std::numeric_limits<double>::min();
+ return true;
+ }
+ if (elapsed*16 < maxElapsed) {
+ countMask = ((countMask<<1)|1) & ((1LL<<60)-1);
+ countMaskInv = 1./(countMask+1);
+ }
}
lastTime = now;
++count;
@@ -64,7 +77,7 @@ bool State::KeepRunning()
// Output results
double average = (now-beginTime)/count;
- std::cout << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n";
+ std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n";
return false;
}
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 5ce13c642b..f13b145aaf 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -40,14 +40,15 @@ namespace benchmark {
std::string name;
double maxElapsed;
double beginTime;
- double lastTime, minTime, maxTime;
+ double lastTime, minTime, maxTime, countMaskInv;
int64_t count;
- int64_t timeCheckCount;
+ int64_t countMask;
public:
State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) {
minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min();
- timeCheckCount = 1;
+ countMask = 1;
+ countMaskInv = 1./(countMask + 1);
}
bool KeepRunning();
};
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index 6b753f6308..168006154f 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -6,6 +6,8 @@
#include "bench.h"
#include "bloom.h"
+#include "hash.h"
+#include "uint256.h"
#include "utiltime.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
@@ -39,6 +41,16 @@ static void SHA256(benchmark::State& state)
CSHA256().Write(begin_ptr(in), in.size()).Finalize(hash);
}
+static void SHA256_32b(benchmark::State& state)
+{
+ std::vector<uint8_t> in(32,0);
+ while (state.KeepRunning()) {
+ for (int i = 0; i < 1000000; i++) {
+ CSHA256().Write(begin_ptr(in), in.size()).Finalize(&in[0]);
+ }
+ }
+}
+
static void SHA512(benchmark::State& state)
{
uint8_t hash[CSHA512::OUTPUT_SIZE];
@@ -47,7 +59,20 @@ static void SHA512(benchmark::State& state)
CSHA512().Write(begin_ptr(in), in.size()).Finalize(hash);
}
+static void SipHash_32b(benchmark::State& state)
+{
+ uint256 x;
+ while (state.KeepRunning()) {
+ for (int i = 0; i < 1000000; i++) {
+ *((uint64_t*)x.begin()) = SipHashUint256(0, i, x);
+ }
+ }
+}
+
BENCHMARK(RIPEMD160);
BENCHMARK(SHA1);
BENCHMARK(SHA256);
BENCHMARK(SHA512);
+
+BENCHMARK(SHA256_32b);
+BENCHMARK(SipHash_32b);
diff --git a/src/init.cpp b/src/init.cpp
index 8688381ecf..98c0894122 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -134,6 +134,11 @@ bool ShutdownRequested()
return fRequestShutdown;
}
+/**
+ * This is a minimally invasive approach to shutdown on LevelDB read errors from the
+ * chainstate, while keeping user interface out of the common library, which is shared
+ * between bitcoind, and bitcoin-qt and non-server tools.
+*/
class CCoinsViewErrorCatcher : public CCoinsViewBacked
{
public:
@@ -1109,6 +1114,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
fListen = GetBoolArg("-listen", DEFAULT_LISTEN);
fDiscover = GetBoolArg("-discover", true);
fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
+ fRelayTxes = !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
bool fBound = false;
if (fListen) {
@@ -1269,8 +1275,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
uiInterface.InitMessage(_("Verifying blocks..."));
if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
- LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n",
- MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", DEFAULT_CHECKBLOCKS));
+ LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks",
+ MIN_BLOCKS_TO_KEEP);
}
{
@@ -1373,10 +1379,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
vImportFiles.push_back(strFile);
}
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
- if (chainActive.Tip() == NULL) {
- LogPrintf("Waiting for genesis block to be imported...\n");
- while (!fRequestShutdown && chainActive.Tip() == NULL)
+
+ // Wait for genesis block to be processed
+ bool fHaveGenesis = false;
+ while (!fHaveGenesis && !fRequestShutdown) {
+ {
+ LOCK(cs_main);
+ fHaveGenesis = (chainActive.Tip() != NULL);
+ }
+
+ if (!fHaveGenesis) {
MilliSleep(10);
+ }
}
// ********************************************************* Step 11: start node
@@ -1387,8 +1401,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!strErrors.str().empty())
return InitError(strErrors.str());
- RandAddSeedPerfmon();
-
//// debug print
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
LogPrintf("nBestHeight = %d\n", chainActive.Height());
diff --git a/src/key.cpp b/src/key.cpp
index 6a3d9aa140..79023566c3 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -124,9 +124,8 @@ bool CKey::Check(const unsigned char *vch) {
}
void CKey::MakeNewKey(bool fCompressedIn) {
- RandAddSeedPerfmon();
do {
- GetRandBytes(vch, sizeof(vch));
+ GetStrongRandBytes(vch, sizeof(vch));
} while (!Check(vch));
fValid = true;
fCompressed = fCompressedIn;
diff --git a/src/main.cpp b/src/main.cpp
index 9ba90b4ead..ffc57d48be 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -40,6 +40,7 @@
#include <sstream>
#include <boost/algorithm/string/replace.hpp>
+#include <boost/algorithm/string/join.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/math/distributions/poisson.hpp>
@@ -2571,16 +2572,10 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
- LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)\n", __func__,
- chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion,
- log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
- DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
- Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
-
cvBlockChange.notify_all();
- // Check the version of the last 100 blocks to see if we need to upgrade:
static bool fWarned = false;
+ std::vector<std::string> warningMessages;
if (!IsInitialBlockDownload())
{
int nUpgraded = 0;
@@ -2596,10 +2591,11 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
fWarned = true;
}
} else {
- LogPrintf("%s: unknown new rules are about to activate (versionbit %i)\n", __func__, bit);
+ warningMessages.push_back(strprintf("unknown new rules are about to activate (versionbit %i)", bit));
}
}
}
+ // Check the version of the last 100 blocks to see if we need to upgrade:
for (int i = 0; i < 100 && pindex != NULL; i++)
{
int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus());
@@ -2608,7 +2604,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
pindex = pindex->pprev;
}
if (nUpgraded > 0)
- LogPrintf("%s: %d of last 100 blocks have unexpected version\n", __func__, nUpgraded);
+ warningMessages.push_back(strprintf("%d of last 100 blocks have unexpected version", nUpgraded));
if (nUpgraded > 100/2)
{
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
@@ -2619,6 +2615,15 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
}
}
}
+ LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)", __func__,
+ chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion,
+ log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
+ DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
+ Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
+ if (!warningMessages.empty())
+ LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", "));
+ LogPrintf("\n");
+
}
/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
@@ -3871,6 +3876,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))));
if (pindex->nHeight < chainActive.Height()-nCheckDepth)
break;
+ if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
+ // If pruning, only go back as far as we have data.
+ LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight);
+ break;
+ }
CBlock block;
// check level 0: read from disk
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
@@ -4537,7 +4547,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
{
- RandAddSeedPerfmon();
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
@@ -4790,7 +4799,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return error("message inv size() = %u", vInv.size());
}
- bool fBlocksOnly = GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
+ bool fBlocksOnly = !fRelayTxes;
// Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistrelay is true
if (pfrom->fWhitelisted && GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))
@@ -4973,7 +4982,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
// Stop processing the transaction early if
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
- if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
+ if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
{
LogPrint("net", "transaction sent in violation of protocol peer=%d\n", pfrom->id);
return true;
diff --git a/src/net.cpp b/src/net.cpp
index bbd23d292a..a0c670e595 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -76,6 +76,7 @@ const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
bool fDiscover = true;
bool fListen = true;
uint64_t nLocalServices = NODE_NETWORK;
+bool fRelayTxes = true;
CCriticalSection cs_mapLocalHost;
std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfLimited[NET_MAX] = {};
@@ -470,7 +471,7 @@ void CNode::PushVersion()
else
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
- nLocalHostNonce, strSubVersion, nBestHeight, !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY));
+ nLocalHostNonce, strSubVersion, nBestHeight, ::fRelayTxes);
}
diff --git a/src/net.h b/src/net.h
index 998ee49260..59176deeeb 100644
--- a/src/net.h
+++ b/src/net.h
@@ -152,6 +152,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
extern bool fDiscover;
extern bool fListen;
extern uint64_t nLocalServices;
+extern bool fRelayTxes;
extern uint64_t nLocalHostNonce;
extern CAddrMan addrman;
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 415bffb991..e8aa79679c 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -77,10 +77,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
AskPassphraseDialog::~AskPassphraseDialog()
{
- // Attempt to overwrite text so that they do not linger around in memory
- ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size()));
- ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size()));
- ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size()));
+ secureClearPassFields();
delete ui;
}
@@ -103,6 +100,8 @@ void AskPassphraseDialog::accept()
newpass1.assign(ui->passEdit2->text().toStdString().c_str());
newpass2.assign(ui->passEdit3->text().toStdString().c_str());
+ secureClearPassFields();
+
switch(mode)
{
case Encrypt: {
@@ -260,3 +259,17 @@ bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event)
}
return QDialog::eventFilter(object, event);
}
+
+static void SecureClearQLineEdit(QLineEdit* edit)
+{
+ // Attempt to overwrite text so that they do not linger around in memory
+ edit->setText(QString(" ").repeated(edit->text().size()));
+ edit->clear();
+}
+
+void AskPassphraseDialog::secureClearPassFields()
+{
+ SecureClearQLineEdit(ui->passEdit1);
+ SecureClearQLineEdit(ui->passEdit2);
+ SecureClearQLineEdit(ui->passEdit3);
+}
diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h
index 727b5a1ada..34bf7ccb31 100644
--- a/src/qt/askpassphrasedialog.h
+++ b/src/qt/askpassphrasedialog.h
@@ -42,6 +42,7 @@ private:
private Q_SLOTS:
void textChanged();
+ void secureClearPassFields();
protected:
bool event(QEvent *event);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 4998848e9f..50c19c3848 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -320,12 +320,14 @@ void BitcoinGUI::createActions()
aboutAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&About %1").arg(tr(PACKAGE_NAME)), this);
aboutAction->setStatusTip(tr("Show information about %1").arg(tr(PACKAGE_NAME)));
aboutAction->setMenuRole(QAction::AboutRole);
+ aboutAction->setEnabled(false);
aboutQtAction = new QAction(platformStyle->TextColorIcon(":/icons/about_qt"), tr("About &Qt"), this);
aboutQtAction->setStatusTip(tr("Show information about Qt"));
aboutQtAction->setMenuRole(QAction::AboutQtRole);
optionsAction = new QAction(platformStyle->TextColorIcon(":/icons/options"), tr("&Options..."), this);
optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(tr(PACKAGE_NAME)));
optionsAction->setMenuRole(QAction::PreferencesRole);
+ optionsAction->setEnabled(false);
toggleHideAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&Show / Hide"), this);
toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
@@ -343,6 +345,8 @@ void BitcoinGUI::createActions()
openRPCConsoleAction = new QAction(platformStyle->TextColorIcon(":/icons/debugwindow"), tr("&Debug window"), this);
openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
+ // initially disable the debug window menu item
+ openRPCConsoleAction->setEnabled(false);
usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
@@ -911,6 +915,14 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
QMainWindow::closeEvent(event);
}
+void BitcoinGUI::showEvent(QShowEvent *event)
+{
+ // enable the debug window when the main window shows up
+ openRPCConsoleAction->setEnabled(true);
+ aboutAction->setEnabled(true);
+ optionsAction->setEnabled(true);
+}
+
#ifdef ENABLE_WALLET
void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
{
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 33639ed5a2..12e7702ed8 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -72,6 +72,7 @@ public:
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
+ void showEvent(QShowEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
bool eventFilter(QObject *object, QEvent *event);
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index d577345e49..6a0404cbf7 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -219,7 +219,7 @@ void OverviewPage::setWalletModel(WalletModel *model)
filter->setDynamicSortFilter(true);
filter->setSortRole(Qt::EditRole);
filter->setShowInactive(false);
- filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
+ filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
ui->listTransactions->setModel(filter);
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index eb6111e682..199a7b2d77 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -203,7 +203,7 @@ void TransactionView::setModel(WalletModel *model)
transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
transactionView->setSortingEnabled(true);
- transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
+ transactionView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder);
transactionView->verticalHeader()->hide();
transactionView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index a0d0e70442..3867310cd6 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -447,7 +447,7 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
bool WalletModel::backupWallet(const QString &filename)
{
- return BackupWallet(*wallet, filename.toLocal8Bit().data());
+ return wallet->BackupWallet(filename.toLocal8Bit().data());
}
// Handlers for core signals
diff --git a/src/random.cpp b/src/random.cpp
index 6155c0d8cf..d9a8cc145e 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -5,14 +5,17 @@
#include "random.h"
+#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
+#include <wincrypt.h>
#endif
#include "serialize.h" // for begin_ptr(vec)
#include "util.h" // for LogPrint()
#include "utilstrencodings.h" // for GetTime()
+#include <stdlib.h>
#include <limits>
#ifndef WIN32
@@ -22,6 +25,12 @@
#include <openssl/err.h>
#include <openssl/rand.h>
+static void RandFailure()
+{
+ LogPrintf("Failed to read randomness, aborting\n");
+ abort();
+}
+
static inline int64_t GetPerformanceCounter()
{
int64_t nCounter = 0;
@@ -43,7 +52,7 @@ void RandAddSeed()
memory_cleanse((void*)&nCounter, sizeof(nCounter));
}
-void RandAddSeedPerfmon()
+static void RandAddSeedPerfmon()
{
RandAddSeed();
@@ -83,14 +92,65 @@ void RandAddSeedPerfmon()
#endif
}
+/** Get 32 bytes of system entropy. */
+static void GetOSRand(unsigned char *ent32)
+{
+#ifdef WIN32
+ HCRYPTPROV hProvider;
+ int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+ if (!ret) {
+ RandFailure();
+ }
+ ret = CryptGenRandom(hProvider, 32, ent32);
+ if (!ret) {
+ RandFailure();
+ }
+ CryptReleaseContext(hProvider, 0);
+#else
+ int f = open("/dev/urandom", O_RDONLY);
+ if (f == -1) {
+ RandFailure();
+ }
+ int have = 0;
+ do {
+ ssize_t n = read(f, ent32 + have, 32 - have);
+ if (n <= 0 || n + have > 32) {
+ RandFailure();
+ }
+ have += n;
+ } while (have < 32);
+ close(f);
+#endif
+}
+
void GetRandBytes(unsigned char* buf, int num)
{
if (RAND_bytes(buf, num) != 1) {
- LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
- assert(false);
+ RandFailure();
}
}
+void GetStrongRandBytes(unsigned char* out, int num)
+{
+ assert(num <= 32);
+ CSHA512 hasher;
+ unsigned char buf[64];
+
+ // First source: OpenSSL's RNG
+ RandAddSeedPerfmon();
+ GetRandBytes(buf, 32);
+ hasher.Write(buf, 32);
+
+ // Second source: OS RNG
+ GetOSRand(buf);
+ hasher.Write(buf, 32);
+
+ // Produce output
+ hasher.Finalize(buf);
+ memcpy(out, buf, num);
+ memory_cleanse(buf, 64);
+}
+
uint64_t GetRand(uint64_t nMax)
{
if (nMax == 0)
diff --git a/src/random.h b/src/random.h
index 1a2d3e8ee2..31b80bd565 100644
--- a/src/random.h
+++ b/src/random.h
@@ -10,11 +10,8 @@
#include <stdint.h>
-/**
- * Seed OpenSSL PRNG with additional entropy data
- */
+/* Seed OpenSSL PRNG with additional entropy data */
void RandAddSeed();
-void RandAddSeedPerfmon();
/**
* Functions to gather random data via the OpenSSL PRNG
@@ -25,6 +22,12 @@ int GetRandInt(int nMax);
uint256 GetRandHash();
/**
+ * Function to gather random data from multiple sources, failing whenever any
+ * of those source fail to provide a result.
+ */
+void GetStrongRandBytes(unsigned char* buf, int num);
+
+/**
* Seed insecure_rand using the random pool.
* @param Deterministic Use a deterministic seed
*/
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index e09af89656..36178bfb4c 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -460,6 +460,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
" \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n"
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
" \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
+ " \"localrelay\": true|false, (bool) true if transaction relay is requested from peers\n"
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
" \"connections\": xxxxx, (numeric) the number of connections\n"
" \"networks\": [ (array) information per network\n"
@@ -494,6 +495,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("subversion", strSubVersion));
obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
+ obj.push_back(Pair("localrelay", fRelayTxes));
obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("networks", GetNetworksInfo()));
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index bec7ebe55f..483fe746ca 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -211,7 +211,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp)
"\nNOTE: By default this function only works sometimes. This is when there is an\n"
"unspent output in the utxo for this transaction. To make it always work,\n"
"you need to maintain a transaction index, using the -txindex command line option or\n"
- "specify the block in which the transaction is included in manually (by blockhash).\n"
+ "specify the block in which the transaction is included manually (by blockhash).\n"
"\nReturn the raw transaction data.\n"
"\nArguments:\n"
"1. \"txids\" (string) A json array of txids to filter\n"
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 04c6fa9625..e43b2ff6c4 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -195,7 +195,6 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
nHashType = test[3].get_int();
sigHashHex = test[4].get_str();
- uint256 sh;
CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
stream >> tx;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 27596929f1..b9f086b092 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -673,38 +673,6 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
}
-CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
-{
- CAmount nBalance = 0;
-
- // Tally wallet transactions
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
- continue;
-
- CAmount nReceived, nSent, nFee;
- wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
-
- if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
- nBalance += nReceived;
- nBalance -= nSent + nFee;
- }
-
- // Tally internal accounting entries
- nBalance += walletdb.GetAccountCreditDebit(strAccount);
-
- return nBalance;
-}
-
-CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
-{
- CWalletDB walletdb(pwalletMain->strWalletFile);
- return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
-}
-
-
UniValue getbalance(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
@@ -775,7 +743,7 @@ UniValue getbalance(const UniValue& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
- CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
+ CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter);
return ValueFromAmount(nBalance);
}
@@ -923,7 +891,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
EnsureWalletIsUnlocked();
// Check funds
- CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
+ CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@@ -1026,7 +994,7 @@ UniValue sendmany(const UniValue& params, bool fHelp)
EnsureWalletIsUnlocked();
// Check funds
- CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
+ CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@@ -1836,7 +1804,7 @@ UniValue backupwallet(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
string strDest = params[0].get_str();
- if (!BackupWallet(*pwalletMain, strDest))
+ if (!pwalletMain->BackupWallet(strDest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
return NullUniValue;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 6b942e29d7..da0d6f272b 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -509,16 +509,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
return false;
CKeyingMaterial vMasterKey;
- RandAddSeedPerfmon();
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
- GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
+ GetStrongRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
CMasterKey kMasterKey;
- RandAddSeedPerfmon();
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
- GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
+ GetStrongRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
CCrypter crypter;
int64_t nStartTime = GetTimeMillis();
@@ -2759,6 +2757,37 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
return ret;
}
+CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter)
+{
+ CWalletDB walletdb(strWalletFile);
+ return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
+}
+
+CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter)
+{
+ CAmount nBalance = 0;
+
+ // Tally wallet transactions
+ for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+ {
+ const CWalletTx& wtx = (*it).second;
+ if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
+ continue;
+
+ CAmount nReceived, nSent, nFee;
+ wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
+
+ if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+ nBalance += nReceived;
+ nBalance -= nSent + nFee;
+ }
+
+ // Tally internal accounting entries
+ nBalance += walletdb.GetAccountCreditDebit(strAccount);
+
+ return nBalance;
+}
+
std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
{
LOCK(cs_wallet);
@@ -3116,8 +3145,6 @@ bool CWallet::InitLoadWallet()
if (fFirstRun)
{
// Create new keyUser and set as default key
- RandAddSeedPerfmon();
-
CPubKey newDefaultKey;
if (walletInstance->GetKeyFromPool(newDefaultKey)) {
walletInstance->SetDefaultKey(newDefaultKey);
@@ -3252,6 +3279,46 @@ bool CWallet::ParameterInteraction()
return true;
}
+bool CWallet::BackupWallet(const std::string& strDest)
+{
+ if (!fFileBacked)
+ return false;
+ while (true)
+ {
+ {
+ LOCK(bitdb.cs_db);
+ if (!bitdb.mapFileUseCount.count(strWalletFile) || bitdb.mapFileUseCount[strWalletFile] == 0)
+ {
+ // Flush log data to the dat file
+ bitdb.CloseDb(strWalletFile);
+ bitdb.CheckpointLSN(strWalletFile);
+ bitdb.mapFileUseCount.erase(strWalletFile);
+
+ // Copy wallet file
+ boost::filesystem::path pathSrc = GetDataDir() / strWalletFile;
+ boost::filesystem::path pathDest(strDest);
+ if (boost::filesystem::is_directory(pathDest))
+ pathDest /= strWalletFile;
+
+ try {
+#if BOOST_VERSION >= 104000
+ boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
+#else
+ boost::filesystem::copy_file(pathSrc, pathDest);
+#endif
+ LogPrintf("copied %s to %s\n", strWalletFile, pathDest.string());
+ return true;
+ } catch (const boost::filesystem::filesystem_error& e) {
+ LogPrintf("error copying %s to %s - %s\n", strWalletFile, pathDest.string(), e.what());
+ return false;
+ }
+ }
+ }
+ MilliSleep(100);
+ }
+ return false;
+}
+
CKeyPool::CKeyPool()
{
nTime = GetTime();
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index cc568c3749..b2180a5a26 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -776,6 +776,8 @@ public:
std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, CAmount> GetAddressBalances();
+ CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter);
+ CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter);
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
isminetype IsMine(const CTxIn& txin) const;
@@ -883,6 +885,8 @@ public:
/* Wallets parameter interaction */
static bool ParameterInteraction();
+
+ bool BackupWallet(const std::string& strDest);
};
/** A key allocated from the key pool. */
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 48579b2821..b5037c9a65 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -903,46 +903,6 @@ void ThreadFlushWalletDB(const string& strFile)
}
}
-bool BackupWallet(const CWallet& wallet, const string& strDest)
-{
- if (!wallet.fFileBacked)
- return false;
- while (true)
- {
- {
- LOCK(bitdb.cs_db);
- if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0)
- {
- // Flush log data to the dat file
- bitdb.CloseDb(wallet.strWalletFile);
- bitdb.CheckpointLSN(wallet.strWalletFile);
- bitdb.mapFileUseCount.erase(wallet.strWalletFile);
-
- // Copy wallet file
- boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
- boost::filesystem::path pathDest(strDest);
- if (boost::filesystem::is_directory(pathDest))
- pathDest /= wallet.strWalletFile;
-
- try {
-#if BOOST_VERSION >= 104000
- boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
-#else
- boost::filesystem::copy_file(pathSrc, pathDest);
-#endif
- LogPrintf("copied %s to %s\n", wallet.strWalletFile, pathDest.string());
- return true;
- } catch (const boost::filesystem::filesystem_error& e) {
- LogPrintf("error copying %s to %s - %s\n", wallet.strWalletFile, pathDest.string(), e.what());
- return false;
- }
- }
- }
- MilliSleep(100);
- }
- return false;
-}
-
//
// Try to (very carefully!) recover wallet file if there is a problem.
//
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 5345c0907e..00c10ea70f 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -141,7 +141,6 @@ private:
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
};
-bool BackupWallet(const CWallet& wallet, const std::string& strDest);
void ThreadFlushWalletDB(const std::string& strFile);
#endif // BITCOIN_WALLET_WALLETDB_H