aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore65
-rw-r--r--Makefile.am159
-rw-r--r--README.md17
-rwxr-xr-xautogen.sh1
-rw-r--r--bitcoin-qt.pro451
-rw-r--r--configure.ac716
-rw-r--r--contrib/README.md50
-rw-r--r--contrib/bitcoin-qt.pro17
-rw-r--r--contrib/bitrpc/README.md2
-rw-r--r--contrib/debian/README20
-rw-r--r--contrib/debian/README.md21
-rw-r--r--contrib/debian/bitcoin-qt.desktop2
-rw-r--r--contrib/debian/changelog24
-rw-r--r--contrib/gitian-descriptors/README.md (renamed from contrib/gitian-descriptors/README)46
-rw-r--r--contrib/gitian-descriptors/boost-win32.yml72
-rw-r--r--contrib/gitian-descriptors/deps-win32.yml65
-rw-r--r--contrib/gitian-descriptors/gitian-win32.yml95
-rw-r--r--contrib/gitian-descriptors/gitian.yml39
-rw-r--r--contrib/gitian-descriptors/protobuf-win32.yml33
-rw-r--r--contrib/gitian-descriptors/qt-win32.yml35
-rw-r--r--contrib/gitian-downloader/linux-download-config4
-rw-r--r--contrib/gitian-downloader/michagogo-key.pgp59
-rw-r--r--contrib/gitian-downloader/win32-download-config4
-rw-r--r--contrib/homebrew/bitcoin.qt.pro.patch32
-rw-r--r--contrib/homebrew/makefile.osx.patch48
-rw-r--r--contrib/linearize/README.md2
-rw-r--r--contrib/linearize/example-linearize.cfg12
-rw-r--r--contrib/linearize/linearize.py129
-rw-r--r--contrib/macdeploy/README.md19
-rwxr-xr-xcontrib/macdeploy/macdeployqtplus17
-rw-r--r--contrib/macdeploy/notes.txt26
-rw-r--r--contrib/pyminer/README.md (renamed from contrib/pyminer/README)3
-rw-r--r--contrib/qos/README.md (renamed from contrib/qos/README)2
-rw-r--r--contrib/seeds/README.md (renamed from contrib/seeds/README)6
-rw-r--r--contrib/spendfrom/README.md (renamed from contrib/spendfrom/README)16
-rw-r--r--contrib/test-patches/README.md (renamed from contrib/test-patches/README)5
-rw-r--r--contrib/testgen/README1
-rw-r--r--contrib/testgen/README.md8
-rw-r--r--contrib/verifysfbinaries/README.md7
-rw-r--r--contrib/wallettools/README.md2
-rw-r--r--doc/README.md22
-rw-r--r--doc/build-unix.md62
-rw-r--r--doc/readme-qt.md128
-rw-r--r--doc/release-process.md28
-rw-r--r--doc/tor.md1
-rw-r--r--doc/translation_process.md11
-rw-r--r--doc/unit-tests.md37
-rw-r--r--pkg.m4214
-rwxr-xr-xqa/pull-tester/build-tests.sh.in74
-rwxr-xr-xqa/pull-tester/pull-tester.py184
-rwxr-xr-xqa/pull-tester/pull-tester.sh15
-rwxr-xr-xqa/pull-tester/run-bitcoind-for-test.sh.in27
-rwxr-xr-xshare/genbuild.sh8
-rw-r--r--share/qt/Info.plist.in (renamed from share/qt/Info.plist)6
-rwxr-xr-xshare/qt/extract_strings_qt.py4
-rw-r--r--share/setup.nsi.in (renamed from share/setup.nsi)324
-rw-r--r--src/.gitignore3
-rw-r--r--src/Makefile.am78
-rw-r--r--src/Makefile.include65
-rw-r--r--src/addrman.cpp5
-rw-r--r--src/addrman.h6
-rw-r--r--src/alert.cpp10
-rw-r--r--src/allocators.cpp64
-rw-r--r--src/allocators.h56
-rw-r--r--src/bitcoind-res.rc36
-rw-r--r--src/bitcoind.cpp18
-rw-r--r--src/bitcoinrpc.cpp199
-rw-r--r--src/bitcoinrpc.h15
-rw-r--r--src/chainparams.h2
-rw-r--r--src/clientversion.h5
-rw-r--r--src/compat.h7
-rw-r--r--src/core.cpp18
-rw-r--r--src/core.h46
-rw-r--r--src/db.cpp30
-rw-r--r--src/db.h2
-rw-r--r--src/init.cpp127
-rw-r--r--src/key.cpp20
-rw-r--r--src/leveldb.cpp8
-rw-r--r--src/leveldb.h5
-rw-r--r--src/leveldb/Makefile6
-rw-r--r--src/leveldb/db/autocompact_test.cc118
-rw-r--r--src/leveldb/db/corruption_test.cc51
-rw-r--r--src/leveldb/db/db_impl.cc41
-rw-r--r--src/leveldb/db/db_impl.h9
-rw-r--r--src/leveldb/db/db_iter.cc41
-rw-r--r--src/leveldb/db/db_iter.h8
-rw-r--r--src/leveldb/db/dbformat.h3
-rw-r--r--src/leveldb/db/version_set.cc96
-rw-r--r--src/leveldb/db/version_set.h15
-rw-r--r--src/leveldb/include/leveldb/db.h2
-rw-r--r--src/leveldb/util/env_posix.cc33
-rw-r--r--src/leveldb/util/random.h7
-rw-r--r--src/m4/ax_boost_base.m4258
-rw-r--r--src/m4/ax_boost_chrono.m4118
-rw-r--r--src/m4/ax_boost_filesystem.m4118
-rw-r--r--src/m4/ax_boost_program_options.m4108
-rw-r--r--src/m4/ax_boost_system.m4120
-rw-r--r--src/m4/ax_boost_thread.m4153
-rw-r--r--src/m4/ax_boost_unit_test_framework.m4137
-rw-r--r--src/m4/ax_check_compile_flag.m472
-rw-r--r--src/m4/ax_check_link_flag.m471
-rw-r--r--src/m4/ax_check_preproc_flag.m472
-rw-r--r--src/m4/ax_pthread.m4317
-rw-r--r--src/m4/bitcoin_find_bdb48.m466
-rw-r--r--src/m4/bitcoin_subdir_to_include.m414
-rw-r--r--src/main.cpp548
-rw-r--r--src/main.h138
-rw-r--r--src/makefile.linux-mingw135
-rw-r--r--src/makefile.mingw143
-rw-r--r--src/makefile.osx181
-rw-r--r--src/makefile.unix206
-rw-r--r--src/miner.cpp40
-rw-r--r--src/miner.h3
-rw-r--r--src/net.cpp158
-rw-r--r--src/net.h45
-rw-r--r--src/netbase.cpp32
-rw-r--r--src/netbase.h6
-rw-r--r--src/noui.cpp4
-rw-r--r--src/protocol.cpp4
-rw-r--r--src/qt/Makefile.am172
-rw-r--r--src/qt/addressbookpage.cpp4
-rw-r--r--src/qt/addresstablemodel.cpp49
-rw-r--r--src/qt/addresstablemodel.h2
-rw-r--r--src/qt/askpassphrasedialog.cpp1
-rw-r--r--src/qt/bitcoin.cpp27
-rw-r--r--src/qt/bitcoinaddressvalidator.h4
-rw-r--r--src/qt/bitcoinamountfield.cpp5
-rw-r--r--src/qt/bitcoingui.cpp54
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/clientmodel.cpp28
-rw-r--r--src/qt/clientmodel.h8
-rw-r--r--src/qt/csvmodelwriter.cpp1
-rw-r--r--src/qt/forms/optionsdialog.ui2
-rw-r--r--src/qt/forms/qrcodedialog.ui2
-rw-r--r--src/qt/forms/rpcconsole.ui261
-rw-r--r--src/qt/forms/sendcoinsdialog.ui2
-rw-r--r--src/qt/forms/sendcoinsentry.ui40
-rw-r--r--src/qt/locale/bitcoin_en.ts197
-rw-r--r--src/qt/notificator.h4
-rw-r--r--src/qt/optionsdialog.cpp4
-rw-r--r--src/qt/optionsmodel.cpp4
-rw-r--r--src/qt/paymentrequestplus.cpp27
-rw-r--r--src/qt/paymentserver.cpp114
-rw-r--r--src/qt/paymentserver.h27
-rw-r--r--src/qt/res/bitcoin-qt-res.rc (renamed from src/qt/res/bitcoin-qt.rc)0
-rw-r--r--src/qt/rpcconsole.cpp55
-rw-r--r--src/qt/rpcconsole.h9
-rw-r--r--src/qt/sendcoinsdialog.cpp169
-rw-r--r--src/qt/sendcoinsdialog.h1
-rw-r--r--src/qt/sendcoinsentry.cpp33
-rw-r--r--src/qt/sendcoinsentry.h3
-rw-r--r--src/qt/test/Makefile.am26
-rw-r--r--src/qt/test/paymentservertests.cpp4
-rw-r--r--src/qt/trafficgraphwidget.cpp169
-rw-r--r--src/qt/trafficgraphwidget.h44
-rw-r--r--src/qt/transactiondesc.cpp33
-rw-r--r--src/qt/transactiondesc.h2
-rw-r--r--src/qt/transactionrecord.cpp15
-rw-r--r--src/qt/transactionrecord.h6
-rw-r--r--src/qt/transactiontablemodel.cpp46
-rw-r--r--src/qt/walletframe.cpp7
-rw-r--r--src/qt/walletmodel.cpp130
-rw-r--r--src/qt/walletmodel.h16
-rw-r--r--src/qt/walletmodeltransaction.cpp56
-rw-r--r--src/qt/walletmodeltransaction.h37
-rw-r--r--src/rpcblockchain.cpp24
-rw-r--r--src/rpcdump.cpp18
-rw-r--r--src/rpcmining.cpp76
-rw-r--r--src/rpcnet.cpp35
-rw-r--r--src/rpcrawtransaction.cpp80
-rw-r--r--src/rpcwallet.cpp73
-rw-r--r--src/script.cpp146
-rw-r--r--src/script.h11
-rw-r--r--src/sync.cpp26
-rw-r--r--src/test/Makefile.am41
-rw-r--r--src/test/alert_tests.cpp26
-rw-r--r--src/test/base58_tests.cpp17
-rw-r--r--src/test/canonical_tests.cpp8
-rw-r--r--src/test/checkblock_tests.cpp2
-rw-r--r--src/test/data/alertTests.raw (renamed from src/test/data/alertTests)bin1283 -> 1283 bytes
-rw-r--r--src/test/miner_tests.cpp16
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/script_tests.cpp35
-rw-r--r--src/test/sighash_tests.cpp120
-rw-r--r--src/test/transaction_tests.cpp8
-rw-r--r--src/test/wallet_tests.cpp1
-rw-r--r--src/txdb.cpp6
-rw-r--r--src/uint256.h94
-rw-r--r--src/util.cpp51
-rw-r--r--src/util.h39
-rw-r--r--src/wallet.cpp75
-rw-r--r--src/wallet.h10
-rw-r--r--src/walletdb.cpp34
193 files changed, 7613 insertions, 3362 deletions
diff --git a/.gitignore b/.gitignore
index bf16a51891..ba6842acaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,46 @@
+*.tar.gz
+
+*.exe
src/*.exe
+src/*/*.exe
src/bitcoin
src/bitcoind
-src/test_bitcoin
+src/test/test_bitcoin
+src/qt/test/test_bitcoin-qt
+
+Makefile.in
+aclocal.m4
+autom4te.cache/
+config.log
+config.status
+configure
+src/.deps/
+src/Makefile.in
+src/bitcoin-config.h
+src/bitcoin-config.h.in
+src/build-aux/
+src/qt/Makefile.in
+src/stamp-h1
+share/setup.nsi
+share/qt/Info.plist
+
+src/leveldb/.deps/
+
+src/test/.deps
+src/test/.dirstamp
+
+src/qt/.deps/
+src/qt/.dirstamp
+src/qt/*.moc
+src/qt/moc_*.cpp
+src/qt/forms/ui_*.h
+
+src/qt/test/.deps/
+src/qt/test/.dirstamp
+src/qt/test/moc*.cpp
+src/qt/res/.deps/
+src/qt/res/.dirstamp
+
.*.swp
*.*~*
*.bak
@@ -10,6 +49,16 @@ src/test_bitcoin
*.o
*.patch
.bitcoin
+*.a
+*.pb.cc
+*.pb.h
+
+*.log
+*.trs
+*.dmg
+
+*.json.h
+*.raw.h
# Compilation and Qt preprocessor part
*.qm
@@ -31,4 +80,18 @@ qrc_*.cpp
.DS_Store
build
+#lcov
+*.gcno
+/*.info
+test_bitcoin.coverage/
+total.coverage/
+coverage_percent.txt
+
+#build tests
+linux-coverage-build
+linux-build
+win32-build
+qa/pull-tester/run-bitcoind-for-test.sh
+qa/pull-tester/build-tests.sh
+
!src/leveldb-*/Makefile
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000000..b4ea94ad62
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,159 @@
+ACLOCAL_AMFLAGS = -I src/m4
+SUBDIRS = src
+.PHONY: deploy
+
+GZIP_ENV="-9n"
+
+BITCOIND_BIN=$(top_builddir)/src/bitcoind$(EXEEXT)
+BITCOIN_QT_BIN=$(top_builddir)/src/qt/bitcoin-qt$(EXEEXT)
+BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win32-setup$(EXEEXT)
+
+OSX_APP=Bitcoin-Qt.app
+OSX_DMG=Bitcoin-Qt.dmg
+OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
+OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
+OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
+OSX_PLIST=$(top_srcdir)/share/qt/Info.plist #not installed
+
+WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
+ $(top_srcdir)/share/pixmaps/nsis-header.bmp \
+ $(top_srcdir)/share/pixmaps/nsis-wizard.bmp \
+ $(top_srcdir)/doc/README_windows.txt
+
+OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
+ $(top_srcdir)/contrib/macdeploy/background.png
+
+COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \
+ leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \
+ baseline_filtered.info block_test_filtered.info \
+ leveldb_baseline_filtered.info test_bitcoin_coverage.info test_bitcoin.info
+
+dist-hook:
+ -$(MAKE) -C $(top_distdir)/src/leveldb clean
+ -$(GIT) archive --format=tar HEAD -- src/version.cpp | $(AMTAR) -C $(top_distdir) -xf -
+
+distcheck-hook:
+ $(MKDIR_P) $(top_distdir)/_build/src/leveldb
+ cp -rf $(top_srcdir)/src/leveldb/* $(top_distdir)/_build/src/leveldb/
+ -$(MAKE) -C $(top_distdir)/_build/src/leveldb clean
+
+distcleancheck:
+ @:
+
+$(BITCOIN_WIN_INSTALLER): $(BITCOIND_BIN) $(BITCOIN_QT_BIN)
+ $(MAKE) distdir
+ $(MKDIR_P) $(top_builddir)/release
+ $(INSTALL_STRIP_PROGRAM) $(top_builddir)/src/bitcoind$(EXEEXT) $(top_builddir)/release
+ $(INSTALL_STRIP_PROGRAM) $(top_builddir)/src/qt/bitcoin-qt$(EXEEXT) $(top_builddir)/release
+ @test -f $(MAKENSIS) && $(MAKENSIS) $(top_builddir)/share/setup.nsi || \
+ echo error: could not build $@
+
+$(BITCOIND_BIN):
+ make -C $(top_srcdir)/src bitcoind$(EXEEXT)
+
+$(BITCOIN_QT_BIN):
+ make -C $(top_srcdir)/src/qt bitcoin-qt$(EXEEXT)
+
+
+$(OSX_APP)/Contents/PkgInfo:
+ $(MKDIR_P) $(@D)
+ @echo "APPL????" > $@
+
+$(OSX_APP)/Contents/Resources/empty.lproj:
+ $(MKDIR_P) $(@D)
+ @touch $@
+
+$(OSX_APP)/Contents/Info.plist: $(OSX_PLIST)
+ $(MKDIR_P) $(@D)
+ $(INSTALL) $< $@
+
+$(OSX_APP)/Contents/Resources/bitcoin.icns: $(OSX_INSTALLER_ICONS)
+ $(MKDIR_P) $(@D)
+ $(INSTALL) $< $@
+
+$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(BITCOIN_QT_BIN)
+ $(MKDIR_P) $(@D)
+ $(INSTALL_STRIP_PROGRAM) $< $@
+
+OSX_APP_BUILT=$(OSX_APP)/Contents/PkgInfo $(OSX_APP)/Contents/Resources/empty.lproj \
+ $(OSX_APP)/Contents/Resources/bitcoin.icns $(OSX_APP)/Contents/Info.plist \
+ $(OSX_APP)/Contents/MacOS/Bitcoin-Qt
+
+$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING)
+ $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2
+ rm -rf $(OSX_APP)
+
+
+if TARGET_DARWIN
+deploy: $(OSX_DMG)
+endif
+if TARGET_WINDOWS
+deploy: $(BITCOIN_WIN_INSTALLER)
+endif
+
+if USE_LCOV
+
+baseline.info:
+ $(LCOV) -c -i -d $(abs_builddir)/src -o $@
+
+baseline_filtered.info: baseline.info
+ $(LCOV) -r $< "/usr/include/*" -o $@
+
+leveldb_baseline.info: baseline_filtered.info
+ $(LCOV) -c -i -d $(abs_builddir)/src/leveldb -b $(abs_builddir)/src/leveldb -o $@
+
+leveldb_baseline_filtered.info: leveldb_baseline.info
+ $(LCOV) -r $< "/usr/include/*" -o $@
+
+baseline_filtered_combined.info: leveldb_baseline_filtered.info baseline_filtered.info
+ $(LCOV) -a leveldb_baseline_filtered.info -a baseline_filtered.info -o $@
+
+test_bitcoin.info: baseline_filtered_combined.info
+ $(MAKE) -C src/ check
+ $(LCOV) -c -d $(abs_builddir)/src -t test_bitcoin -o $@
+ $(LCOV) -z -d $(abs_builddir)/src
+ $(LCOV) -z -d $(abs_builddir)/src/leveldb
+
+test_bitcoin_filtered.info: test_bitcoin.info
+ $(LCOV) -r $< "/usr/include/*" -o $@
+
+block_test.info: test_bitcoin_filtered.info
+ -@TIMEOUT=15 qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -Xmx2G -jar $(JAVA_COMPARISON_TOOL) 1 18444
+ $(LCOV) -c -d $(abs_builddir)/src --t BitcoinJBlockTest -o $@
+ $(LCOV) -z -d $(abs_builddir)/src
+ $(LCOV) -z -d $(abs_builddir)/src/leveldb
+
+block_test_filtered.info: block_test.info
+ $(LCOV) -r $< "/usr/include/*" -o $@
+
+test_bitcoin_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info
+ $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -o $@
+
+total_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info block_test_filtered.info
+ $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -a block_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
+
+test_bitcoin.coverage/.dirstamp: test_bitcoin_coverage.info
+ $(GENHTML) -s $< -o $(@D)
+ @touch $@
+
+total.coverage/.dirstamp: total_coverage.info
+ $(GENHTML) -s $< -o $(@D)
+ @touch $@
+
+cov: test_bitcoin.coverage/.dirstamp total.coverage/.dirstamp
+
+endif
+
+if USE_COMPARISON_TOOL
+check-local:
+ @qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -Xmx2G -jar $(JAVA_COMPARISON_TOOL) 1 18444
+endif
+
+EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/pull-tester.sh $(WINDOWS_PACKAGING) $(OSX_PACKAGING)
+
+CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
+
+.INTERMEDIATE: $(OSX_APP_BUILT) $(COVERAGE_INFO)
+
+clean-local:
+ rm -rf test_bitcoin.coverage/ total.coverage/
diff --git a/README.md b/README.md
index 5453f998dc..2534a62b08 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ the Bitcoin client software, see http://www.bitcoin.org.
License
-------
-Bitcoin is released under the terms of the MIT license. See `COPYING` for more
+Bitcoin is released under the terms of the MIT license. See [COPYING](COPYING) for more
information or see http://opensource.org/licenses/MIT.
Development process
@@ -38,7 +38,7 @@ submitter will be asked to start a discussion (if they haven't already) on the
The patch will be accepted if there is broad consensus that it is a good thing.
Developers should expect to rework and resubmit patches if the code doesn't
-match the project's coding conventions (see `doc/coding.md`) or are
+match the project's coding conventions (see [doc/coding.md](doc/coding.md)) or are
controversial.
The `master` branch is regularly built and tested, but is not guaranteed to be
@@ -56,17 +56,7 @@ lots of money.
### Automated Testing
Developers are strongly encouraged to write unit tests for new code, and to
-submit new unit tests for old code.
-
-Unit tests for the core code are in `src/test/`. To compile and run them:
-
- cd src; make -f makefile.unix test
-
-Unit tests for the GUI code are in `src/qt/test/`. To compile and run them:
-
- qmake BITCOIN_QT_TEST=1 -o Makefile.test bitcoin-qt.pro
- make -f Makefile.test
- ./bitcoin-qt_test
+submit new unit tests for old code. Unit tests can be compiled and run (assuming they weren't disabled in configure) with: `make check`
Every pull request is built for both Windows and Linux on a dedicated server,
and unit and sanity tests are automatically run. The binaries produced may be
@@ -78,5 +68,4 @@ for the build/test scripts.
Large changes should have a test plan, and should be tested by somebody other
than the developer who wrote the code.
-
See https://github.com/bitcoin/QA/ for how to create a test plan.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000000..4e7011a596
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1 @@
+autoreconf -vif
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
deleted file mode 100644
index 9baa03a4e3..0000000000
--- a/bitcoin-qt.pro
+++ /dev/null
@@ -1,451 +0,0 @@
-TEMPLATE = app
-TARGET = bitcoin-qt
-macx:TARGET = "Bitcoin-Qt"
-VERSION = 0.8.2
-INCLUDEPATH += src src/json src/qt
-QT += core gui network
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-DEFINES += BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
-CONFIG += no_include_pwd
-CONFIG += thread
-
-# for boost 1.37, add -mt to the boost libraries
-# use: qmake BOOST_LIB_SUFFIX=-mt
-# for boost thread win32 with _win32 sufix
-# use: BOOST_THREAD_LIB_SUFFIX=_win32-...
-# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-4.8
-
-# Dependency library locations can be customized with:
-# BOOST_INCLUDE_PATH BOOST_LIB_PATH,
-# BDB_INCLUDE_PATH BDB_LIB_PATH,
-# OPENSSL_INCLUDE_PATH OPENSSL_LIB_PATH
-# PROTOBUF_INCLUDE_PATH PROTOBUF_LIB_PATH
-# PROTOC : protocol buffer compiler tool
-
-OBJECTS_DIR = build
-MOC_DIR = build
-UI_DIR = build
-PROTO_DIR = build
-PROTO_PATH = src/qt
-
-contains(BITCOIN_QT_TEST, 1) {
-OBJECTS_DIR = build_test
-MOC_DIR = build_test
-UI_DIR = build_test
-PROTO_DIR = build_test
-
-SOURCES += src/qt/test/test_main.cpp \
- src/qt/test/uritests.cpp \
- src/qt/test/paymentservertests.cpp
-HEADERS += src/qt/test/uritests.h \
- src/qt/test/paymentservertests.h
-DEPENDPATH += src/qt/test
-QT += testlib
-TARGET = bitcoin-qt_test
-DEFINES += BITCOIN_QT_TEST
-macx: CONFIG -= app_bundle
-}
-
-# use: qmake "RELEASE=1"
-contains(RELEASE, 1) {
- # Mac: compile for maximum compatibility (10.5, 32-bit)
- macx:QMAKE_CXXFLAGS += -mmacosx-version-min=10.5 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk
- macx:QMAKE_CFLAGS += -mmacosx-version-min=10.5 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk
- macx:QMAKE_OBJECTIVE_CFLAGS += -mmacosx-version-min=10.5 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk
-
- !win32:!macx {
- # Linux: static link and extra security (see: https://wiki.debian.org/Hardening)
- LIBS += -Wl,-Bstatic -Wl,-z,relro -Wl,-z,now
- }
-}
-
-!win32 {
- # for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection
- QMAKE_CXXFLAGS *= -fstack-protector-all
- QMAKE_LFLAGS *= -fstack-protector-all
- # Exclude on Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable!
- # This can be enabled for Windows, when we switch to MinGW >= 4.4.x.
-}
-# for extra security (see: https://wiki.debian.org/Hardening): this flag is GCC compiler-specific
-QMAKE_CXXFLAGS *= -D_FORTIFY_SOURCE=2
-# for extra security on Windows: enable ASLR and DEP via GCC linker flags
-win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat
-# on Windows: enable GCC large address aware linker flag
-win32:QMAKE_LFLAGS *= -Wl,--large-address-aware
-
-# use: qmake "USE_QRCODE=1"
-# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
-contains(USE_QRCODE, 1) {
- message(Building with QRCode support)
- DEFINES += USE_QRCODE
- LIBS += -lqrencode
-}
-
-# use: qmake "USE_UPNP=1" ( enabled by default; default)
-# or: qmake "USE_UPNP=0" (disabled by default)
-# or: qmake "USE_UPNP=-" (not supported)
-# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support
-contains(USE_UPNP, -) {
- message(Building without UPNP support)
-} else {
- message(Building with UPNP support)
- count(USE_UPNP, 0) {
- USE_UPNP=1
- }
- DEFINES += USE_UPNP=$$USE_UPNP STATICLIB
- INCLUDEPATH += $$MINIUPNPC_INCLUDE_PATH
- LIBS += $$join(MINIUPNPC_LIB_PATH,,-L,) -lminiupnpc
- win32:LIBS += -liphlpapi
-}
-
-# use: qmake "USE_DBUS=1"
-contains(USE_DBUS, 1) {
- message(Building with DBUS (Freedesktop notifications) support)
- DEFINES += USE_DBUS
- QT += dbus
-}
-
-# use: qmake "USE_IPV6=1" ( enabled by default; default)
-# or: qmake "USE_IPV6=0" (disabled by default)
-# or: qmake "USE_IPV6=-" (not supported)
-contains(USE_IPV6, -) {
- message(Building without IPv6 support)
-} else {
- count(USE_IPV6, 0) {
- USE_IPV6=1
- }
- DEFINES += USE_IPV6=$$USE_IPV6
-}
-
-contains(BITCOIN_NEED_QT_PLUGINS, 1) {
- DEFINES += BITCOIN_NEED_QT_PLUGINS
- QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets
-}
-
-INCLUDEPATH += src/leveldb/include src/leveldb/helpers
-LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a
-!win32 {
- # we use QMAKE_CXXFLAGS_RELEASE even without RELEASE=1 because we use RELEASE to indicate linking preferences not -O preferences
- genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a
-} else {
- # make an educated guess about what the ranlib command is called
- isEmpty(QMAKE_RANLIB) {
- QMAKE_RANLIB = $$replace(QMAKE_STRIP, strip, ranlib)
- }
- LIBS += -lshlwapi
- genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a
-}
-genleveldb.target = $$PWD/src/leveldb/libleveldb.a
-genleveldb.depends = FORCE
-PRE_TARGETDEPS += $$PWD/src/leveldb/libleveldb.a
-QMAKE_EXTRA_TARGETS += genleveldb
-# Gross ugly hack that depends on qmake internals, unfortunately there is no other way to do it.
-QMAKE_CLEAN += $$PWD/src/leveldb/libleveldb.a; cd $$PWD/src/leveldb ; $(MAKE) clean
-
-# regenerate build.h
-!win32|contains(USE_BUILD_INFO, 1) {
- genbuild.depends = FORCE
- genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OBJECTS_DIR/build.h
- genbuild.target = $$OBJECTS_DIR/build.h
- PRE_TARGETDEPS += $$OBJECTS_DIR/build.h
- QMAKE_EXTRA_TARGETS += genbuild
- DEFINES += HAVE_BUILD_INFO
-}
-
-QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector
-
-# Input
-DEPENDPATH += src src/json src/qt
-HEADERS += src/qt/bitcoingui.h \
- src/qt/transactiontablemodel.h \
- src/qt/addresstablemodel.h \
- src/qt/optionsdialog.h \
- src/qt/sendcoinsdialog.h \
- src/qt/addressbookpage.h \
- src/qt/signverifymessagedialog.h \
- src/qt/aboutdialog.h \
- src/qt/editaddressdialog.h \
- src/qt/bitcoinaddressvalidator.h \
- src/alert.h \
- src/addrman.h \
- src/base58.h \
- src/bignum.h \
- src/chainparams.h \
- src/checkpoints.h \
- src/compat.h \
- src/sync.h \
- src/util.h \
- src/hash.h \
- src/uint256.h \
- src/serialize.h \
- src/core.h \
- src/main.h \
- src/miner.h \
- src/net.h \
- src/key.h \
- src/db.h \
- src/walletdb.h \
- src/script.h \
- src/init.h \
- src/bloom.h \
- src/mruset.h \
- src/checkqueue.h \
- src/json/json_spirit_writer_template.h \
- src/json/json_spirit_writer.h \
- src/json/json_spirit_value.h \
- src/json/json_spirit_utils.h \
- src/json/json_spirit_stream_reader.h \
- src/json/json_spirit_reader_template.h \
- src/json/json_spirit_reader.h \
- src/json/json_spirit_error_position.h \
- src/json/json_spirit.h \
- src/qt/clientmodel.h \
- src/qt/guiutil.h \
- src/qt/transactionrecord.h \
- src/qt/guiconstants.h \
- src/qt/optionsmodel.h \
- src/qt/monitoreddatamapper.h \
- src/qt/transactiondesc.h \
- src/qt/transactiondescdialog.h \
- src/qt/bitcoinamountfield.h \
- src/wallet.h \
- src/keystore.h \
- src/qt/transactionfilterproxy.h \
- src/qt/transactionview.h \
- src/qt/walletmodel.h \
- src/qt/walletview.h \
- src/qt/walletstack.h \
- src/qt/walletframe.h \
- src/bitcoinrpc.h \
- src/qt/overviewpage.h \
- src/qt/csvmodelwriter.h \
- src/crypter.h \
- src/qt/sendcoinsentry.h \
- src/qt/qvalidatedlineedit.h \
- src/qt/bitcoinunits.h \
- src/qt/qvaluecombobox.h \
- src/qt/askpassphrasedialog.h \
- src/protocol.h \
- src/qt/notificator.h \
- src/qt/paymentrequestplus.h \
- src/qt/paymentserver.h \
- src/allocators.h \
- src/ui_interface.h \
- src/qt/rpcconsole.h \
- src/version.h \
- src/netbase.h \
- src/clientversion.h \
- src/txdb.h \
- src/leveldb.h \
- src/threadsafety.h \
- src/limitedmap.h \
- src/qt/splashscreen.h \
- src/qt/intro.h
-
-SOURCES += src/qt/bitcoin.cpp \
- src/qt/bitcoingui.cpp \
- src/qt/transactiontablemodel.cpp \
- src/qt/addresstablemodel.cpp \
- src/qt/optionsdialog.cpp \
- src/qt/sendcoinsdialog.cpp \
- src/qt/addressbookpage.cpp \
- src/qt/signverifymessagedialog.cpp \
- src/qt/aboutdialog.cpp \
- src/qt/editaddressdialog.cpp \
- src/qt/bitcoinaddressvalidator.cpp \
- src/alert.cpp \
- src/chainparams.cpp \
- src/version.cpp \
- src/sync.cpp \
- src/util.cpp \
- src/hash.cpp \
- src/netbase.cpp \
- src/key.cpp \
- src/script.cpp \
- src/core.cpp \
- src/main.cpp \
- src/init.cpp \
- src/miner.cpp \
- src/net.cpp \
- src/bloom.cpp \
- src/checkpoints.cpp \
- src/addrman.cpp \
- src/db.cpp \
- src/walletdb.cpp \
- src/qt/clientmodel.cpp \
- src/qt/guiutil.cpp \
- src/qt/transactionrecord.cpp \
- src/qt/optionsmodel.cpp \
- src/qt/monitoreddatamapper.cpp \
- src/qt/transactiondesc.cpp \
- src/qt/transactiondescdialog.cpp \
- src/qt/bitcoinstrings.cpp \
- src/qt/bitcoinamountfield.cpp \
- src/wallet.cpp \
- src/keystore.cpp \
- src/qt/transactionfilterproxy.cpp \
- src/qt/transactionview.cpp \
- src/qt/walletmodel.cpp \
- src/qt/walletview.cpp \
- src/qt/walletstack.cpp \
- src/qt/walletframe.cpp \
- src/bitcoinrpc.cpp \
- src/rpcdump.cpp \
- src/rpcnet.cpp \
- src/rpcmining.cpp \
- src/rpcwallet.cpp \
- src/rpcblockchain.cpp \
- src/rpcrawtransaction.cpp \
- src/qt/overviewpage.cpp \
- src/qt/csvmodelwriter.cpp \
- src/crypter.cpp \
- src/qt/sendcoinsentry.cpp \
- src/qt/qvalidatedlineedit.cpp \
- src/qt/bitcoinunits.cpp \
- src/qt/qvaluecombobox.cpp \
- src/qt/askpassphrasedialog.cpp \
- src/protocol.cpp \
- src/qt/notificator.cpp \
- src/qt/paymentrequestplus.cpp \
- src/qt/paymentserver.cpp \
- src/qt/rpcconsole.cpp \
- src/noui.cpp \
- src/leveldb.cpp \
- src/txdb.cpp \
- src/qt/splashscreen.cpp \
- src/qt/intro.cpp
-
-RESOURCES += src/qt/bitcoin.qrc
-
-FORMS += src/qt/forms/sendcoinsdialog.ui \
- src/qt/forms/addressbookpage.ui \
- src/qt/forms/signverifymessagedialog.ui \
- src/qt/forms/aboutdialog.ui \
- src/qt/forms/editaddressdialog.ui \
- src/qt/forms/transactiondescdialog.ui \
- src/qt/forms/overviewpage.ui \
- src/qt/forms/sendcoinsentry.ui \
- src/qt/forms/askpassphrasedialog.ui \
- src/qt/forms/rpcconsole.ui \
- src/qt/forms/optionsdialog.ui \
- src/qt/forms/intro.ui
-
-PROTOS = src/qt/paymentrequest.proto
-include(share/qt/protobuf.pri)
-
-contains(USE_QRCODE, 1) {
-HEADERS += src/qt/qrcodedialog.h
-SOURCES += src/qt/qrcodedialog.cpp
-FORMS += src/qt/forms/qrcodedialog.ui
-}
-
-# Todo: Remove this line when switching to Qt5, as that option was removed
-CODECFORTR = UTF-8
-
-# for lrelease/lupdate
-# also add new translations to src/qt/bitcoin.qrc under translations/
-TRANSLATIONS = $$files(src/qt/locale/bitcoin_*.ts)
-
-isEmpty(QMAKE_LRELEASE) {
- win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
- else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
-}
-isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale
-# automatically build translations, so they can be included in resource file
-TSQM.name = lrelease ${QMAKE_FILE_IN}
-TSQM.input = TRANSLATIONS
-TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm
-TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
-TSQM.CONFIG = no_link
-QMAKE_EXTRA_COMPILERS += TSQM
-
-# "Other files" to show in Qt Creator
-OTHER_FILES += README.md \
- doc/*.txt \
- doc/*.md \
- src/bitcoind.cpp \
- src/qt/res/bitcoin-qt.rc \
- src/test/*.cpp \
- src/test/*.h \
- src/qt/test/*.cpp \
- src/qt/test/*.h
-
-# platform specific defaults, if not overridden on command line
-isEmpty(BOOST_LIB_SUFFIX) {
- macx:BOOST_LIB_SUFFIX = -mt
- win32:BOOST_LIB_SUFFIX = -mgw44-mt-s-1_50
-}
-
-isEmpty(BOOST_THREAD_LIB_SUFFIX) {
- BOOST_THREAD_LIB_SUFFIX = $$BOOST_LIB_SUFFIX
-}
-
-isEmpty(BDB_LIB_PATH) {
- macx:BDB_LIB_PATH = /opt/local/lib/db48
-}
-
-isEmpty(BDB_LIB_SUFFIX) {
- macx:BDB_LIB_SUFFIX = -4.8
-}
-
-isEmpty(BDB_INCLUDE_PATH) {
- macx:BDB_INCLUDE_PATH = /opt/local/include/db48
-}
-
-isEmpty(BOOST_LIB_PATH) {
- macx:BOOST_LIB_PATH = /opt/local/lib
-}
-
-isEmpty(BOOST_INCLUDE_PATH) {
- macx:BOOST_INCLUDE_PATH = /opt/local/include
-}
-
-win32:DEFINES += WIN32
-win32:RC_FILE = src/qt/res/bitcoin-qt.rc
-
-win32:!contains(MINGW_THREAD_BUGFIX, 0) {
- # At least qmake's win32-g++-cross profile is missing the -lmingwthrd
- # thread-safety flag. GCC has -mthreads to enable this, but it doesn't
- # work with static linking. -lmingwthrd must come BEFORE -lmingw, so
- # it is prepended to QMAKE_LIBS_QT_ENTRY.
- # It can be turned off with MINGW_THREAD_BUGFIX=0, just in case it causes
- # any problems on some untested qmake profile now or in the future.
- DEFINES += _MT
- QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY
-}
-
-!win32:!macx {
- DEFINES += LINUX
- LIBS += -lrt
- # _FILE_OFFSET_BITS=64 lets 32-bit fopen transparently support large files.
- DEFINES += _FILE_OFFSET_BITS=64
-}
-
-macx:HEADERS += src/qt/macdockiconhandler.h src/qt/macnotificationhandler.h
-macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm src/qt/macnotificationhandler.mm
-macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit -framework CoreServices
-macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
-macx:ICON = src/qt/res/icons/bitcoin.icns
-macx:QMAKE_CFLAGS_THREAD += -pthread
-macx:QMAKE_LFLAGS_THREAD += -pthread
-macx:QMAKE_CXXFLAGS_THREAD += -pthread
-macx:QMAKE_INFO_PLIST = share/qt/Info.plist
-
-# Set libraries and includes at end, to use platform-defined defaults if not overridden
-INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$PROTOBUF_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH
-LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(PROTOBUF_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,)
-LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX -lprotobuf
-# -lgdi32 has to happen after -lcrypto (see #681)
-win32:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32
-LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX
-win32:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX
-macx:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX
-
-contains(RELEASE, 1) {
- !win32:!macx {
- # Linux: turn dynamic linking back on for c/c++ runtime libraries
- LIBS += -Wl,-Bdynamic
- }
-}
-
-system($$QMAKE_LRELEASE -silent $$TRANSLATIONS)
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000000..905acd573c
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,716 @@
+dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
+AC_PREREQ([2.60])
+define(_CLIENT_VERSION_MAJOR, 0)
+define(_CLIENT_VERSION_MINOR, 8)
+define(_CLIENT_VERSION_REVISION, 99)
+define(_CLIENT_VERSION_BUILD, 0)
+define(_CLIENT_VERSION_IS_RELEASE, false)
+define(_COPYRIGHT_YEAR, 2013)
+AC_INIT([Bitcoin],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@bitcoin.org],[bitcoin])
+AC_CONFIG_AUX_DIR([src/build-aux])
+AC_CONFIG_MACRO_DIR([src/m4])
+AC_CANONICAL_HOST
+AH_TOP([#ifndef BITCOIN_CONFIG_H])
+AH_TOP([#define BITCOIN_CONFIG_H])
+AH_BOTTOM([#endif //BITCOIN_CONFIG_H])
+
+# This m4 will only be used if a system copy cannot be found. This is helpful
+# on systems where autotools are installed but the pkg-config macros are not in
+# a default location. It is currently used for building on OSX where autotools
+# are preinstalled but pkg-config comes from macports or homebrew. It should
+# probably be removed when building on <= 10.6 is no longer supported.
+m4_include([pkg.m4])
+
+dnl faketime breaks configure and is only needed for make. Disable it here.
+unset FAKETIME
+
+dnl ==============================================================
+dnl Setup for automake
+dnl ==============================================================
+
+AM_INIT_AUTOMAKE([no-define subdir-objects foreign])
+
+dnl faketime messes with timestamps and causes configure to be re-run.
+dnl --disable-maintainer-mode can be used to bypass this.
+AM_MAINTAINER_MODE([enable])
+
+dnl make the compilation flags quiet unless V=1 is used
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_ARG_WITH([miniupnpc],
+ [AS_HELP_STRING([--with-miniupnpc],
+ [enable UPNP (default is yes if libminiupnpc is found)])],
+ [use_upnp=$withval],
+ [use_upnp=auto])
+
+AC_ARG_ENABLE([upnp-default],
+ [AS_HELP_STRING([--enable-upnp-default],
+ [if UPNP is enabled, turn it on at startup (default is no)])],
+ [use_upnp_default=$enableval],
+ [use_upnp_default=no])
+
+dnl enable ipv6 support
+AC_ARG_ENABLE([ipv6],
+ [AS_HELP_STRING([--enable-ipv6],
+ [enable ipv6 (default is yes)])],
+ [use_ipv6=$enableval],
+ [use_ipv6=yes])
+
+dnl enable qt support
+AC_ARG_WITH([qt],
+ [AS_HELP_STRING([--with-qt],
+ [enable qt (default is yes)])],
+ [use_qt=$withval],
+ [use_qt=yes])
+
+AC_ARG_ENABLE(tests,
+ AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]),
+ [use_tests=$enableval],
+ [use_tests=yes])
+
+AC_ARG_WITH([comparison-tool],
+ AS_HELP_STRING([with-comparison-tool],[path to java comparison tool (requires --enable-tests)]),
+ [use_comparison_tool=$withval],
+ [use_comparison_tool=no])
+
+AC_ARG_WITH([qrencode],
+ [AS_HELP_STRING([--with-qrencode],
+ [enable QR code support (default is yes if qt is enabled and libqrencode is found)])],
+ [use_qr=$withval],
+ [use_qr=auto])
+
+AC_ARG_WITH([qtdbus],
+ [AS_HELP_STRING([--with-qtdbus],
+ [enable DBus support (default is yes if qt is enabled and QtDBus is found)])],
+ [use_dbus=$withval],
+ [use_dbus=auto])
+
+AC_ARG_ENABLE([hardening],
+ [AS_HELP_STRING([--enable-hardening],
+ [attempt to harden the resulting executables (default is yes)])],
+ [use_hardening=$enableval],
+ [use_hardening=yes])
+
+AC_ARG_ENABLE([ccache],
+ [AS_HELP_STRING([--enable-ccache],
+ [enable building with ccache (default is yes if ccache is found)])],
+ [use_ccache=$enableval],
+ [use_ccache=auto])
+
+AC_ARG_ENABLE([lcov],
+ [AS_HELP_STRING([--enable-lcov],
+ [enable lcov testing (default is no)])],
+ [use_lcov=yes],
+ [use_lcov=no])
+
+AC_ARG_WITH([qt-incdir],[AS_HELP_STRING([--with-qt-incdir=INC_DIR],[specify qt include path (overridden by pkgconfig)])], [qt_include_path=$withval], [])
+AC_ARG_WITH([qt-libdir],[AS_HELP_STRING([--with-qt-libdir=LIB_DIR],[specify qt lib path (overridden by pkgconfig)])], [qt_lib_path=$withval], [])
+AC_ARG_WITH([qt-bindir],[AS_HELP_STRING([--with-qt-bindir=BIN_DIR],[specify qt bin path])], [qt_bin_path=$withval], [])
+AC_ARG_WITH([qt-plugindir],[AS_HELP_STRING([--with-qt-plugindir=PLUGIN_DIR],[specify qt plugin path (overridden by pkgconfig)])], [qt_plugin_path=$withval], [])
+AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], [])
+
+
+AC_CONFIG_SRCDIR([src])
+AC_CONFIG_HEADERS([src/bitcoin-config.h])
+
+dnl Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_CXXCPP
+AC_PROG_INSTALL
+AC_PROG_OBJC
+m4_ifdef([AC_PROG_OBJCXX],[AC_PROG_OBJCXX])
+AC_PROG_MKDIR_P
+AC_PROG_SED
+AC_PATH_TOOL(AR, ar)
+AC_PATH_TOOL(RANLIB, ranlib)
+AC_PATH_TOOL(STRIP, strip)
+AC_PATH_TOOL(GCOV, gcov)
+AC_PATH_PROG(LCOV, lcov)
+AC_PATH_PROG(JAVA, java)
+AC_PATH_PROG(GENHTML, genhtml)
+AC_PATH_PROG([GIT], [git])
+AC_PATH_PROGS([MOC], [moc-qt4 moc4 moc],, $qt_bin_path:$PATH)
+AC_PATH_PROGS([UIC], [uic-qt4 uic4 uic],, $qt_bin_path:$PATH)
+AC_PATH_PROGS([RCC], [rcc-qt4 rcc4 rcc],, $qt_bin_path:$PATH)
+AC_PATH_PROGS([LRELEASE], [lrelease-qt4 lrelease4 lrelease],, $qt_bin_path:$PATH)
+AC_PATH_PROGS([LUPDATE], [lupdate-qt4 lupdate4 lupdate],, $qt_bin_path:$PATH)
+AC_PATH_PROG([PROTOC], [protoc],, $protoc_bin_path:$PATH)
+AC_PATH_PROG(CCACHE,ccache)
+AC_PATH_PROG(XGETTEXT,xgettext)
+AC_PATH_PROG(HEXDUMP,hexdump)
+PKG_PROG_PKG_CONFIG
+
+## TODO: Remove these hard-coded paths and flags. They are here for the sake of
+## compatibility with the legacy buildsystem.
+##
+CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter"
+CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO"
+
+AC_LANG_PUSH([C++])
+
+use_pkgconfig=yes
+case $host in
+ *mingw*)
+
+ #pkgconfig does more harm than good with MinGW
+ use_pkgconfig=no
+
+ TARGET_OS=windows
+ AC_CHECK_LIB([mingwthrd], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([kernel32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([user32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([gdi32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([comdlg32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([winspool], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([winmm], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([shell32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([comctl32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([ole32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([oleaut32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([uuid], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([rpcrt4], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([advapi32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([ws2_32], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([mswsock], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([shlwapi], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([iphlpapi], [main],, AC_MSG_ERROR(lib missing))
+ AC_CHECK_LIB([crypt32], [main],, AC_MSG_ERROR(lib missing))
+
+ AX_CHECK_LINK_FLAG([[-static-libgcc]],[LDFLAGS="$LDFLAGS -static-libgcc"])
+ AX_CHECK_LINK_FLAG([[-static-libstdc++]],[LDFLAGS="$LDFLAGS -static-libstdc++"])
+
+ AC_PATH_PROG([MAKENSIS], [makensis], none)
+ if test x$MAKENSIS = xnone; then
+ AC_MSG_WARN("makensis not found. Cannot create installer.")
+ fi
+
+ AC_PATH_TOOL(WINDRES, windres, none)
+ if test x$WINDRES = xnone; then
+ AC_MSG_ERROR("windres not found")
+ fi
+
+ CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB"
+ LEVELDB_TARGET_FLAGS="TARGET_OS=OS_WINDOWS_CROSSCOMPILE"
+ CXXFLAGS="$CXXFLAGS -w"
+ ;;
+ *darwin*)
+ TARGET_OS=darwin
+ LEVELDB_TARGET_FLAGS="TARGET_OS=Darwin"
+ if test x$cross_compiling != xyes; then
+ AC_CHECK_PROG([PORT],port, port)
+ if test x$PORT = xport; then
+ dnl add default macports paths
+ CPPFLAGS="$CPPFLAGS -I/opt/local/include -I/opt/local/include/db48"
+ LIBS="$LIBS -L/opt/local/lib -L/opt/local/lib/db48"
+ fi
+
+ AC_CHECK_PROG([BREW],brew, brew)
+ if test x$BREW = xbrew; then
+ dnl add default homebrew paths
+ openssl_prefix=`$BREW --prefix openssl`
+ bdb_prefix=`$BREW --prefix berkeley-db4`
+ export PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH"
+ CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include"
+ LIBS="$LIBS -L/$bdb_prefix/lib"
+ fi
+ fi
+
+ if test x$use_qt = xyes; then
+ MOC_DEFS="-DQ_OS_MAC"
+ base_frameworks="-framework Foundation -framework ApplicationServices -framework AppKit"
+ AX_CHECK_LINK_FLAG([[$base_frameworks]],[LIBS="$LIBS $base_frameworks"],[AC_MSG_ERROR(could not find base frameworks)])
+ fi
+
+ CPPFLAGS="$CPPFLAGS -DMAC_OSX"
+ TESTDEFS="-DBOOST_TEST_DYN_LINK"
+ ;;
+ *)
+ TESTDEFS="-DBOOST_TEST_DYN_LINK"
+ ;;
+esac
+
+if test x$use_comparison_tool != xno; then
+ AC_SUBST(JAVA_COMPARISON_TOOL, $use_comparison_tool)
+fi
+
+if test x$use_lcov == xyes; then
+ if test x$LCOV == x; then
+ AC_MSG_ERROR("lcov testing requested but lcov not found")
+ fi
+ if test x$GCOV == x; then
+ AC_MSG_ERROR("lcov testing requested but gcov not found")
+ fi
+ if test x$JAVA == x; then
+ AC_MSG_ERROR("lcov testing requested but java not found")
+ fi
+ if test x$GENHTML == x; then
+ AC_MSG_ERROR("lcov testing requested but genhtml not found")
+ fi
+ if test x$use_comparison_tool == x; then
+ AC_MSG_ERROR("lcov testing requested but comparison tool was not specified")
+ fi
+ LCOV="$LCOV --gcov-tool=$GCOV"
+ AX_CHECK_COMPILE_FLAG([--coverage],[CXXFLAGS="$CXXFLAGS --coverage"],
+ [AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")])
+fi
+
+dnl Require little endian
+AC_C_BIGENDIAN([AC_MSG_ERROR("Big Endian not supported")])
+
+dnl Check for pthread compile/link requirements
+AX_PTHREAD
+INCLUDES="$INCLUDES $PTHREAD_CFLAGS"
+
+# The following macro will add the necessary defines to bitcoin-config.h, but
+# they also need to be passed down to any subprojects. Pull the results out of
+# the cache and add them to CPPFLAGS.
+AC_SYS_LARGEFILE
+
+if test x$ac_cv_sys_file_offset_bits != x &&
+ test x$ac_cv_sys_file_offset_bits != xno &&
+ test x$ac_cv_sys_file_offset_bits != xunknown; then
+ CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
+fi
+
+if test x$ac_cv_sys_large_files != x &&
+ test x$ac_cv_sys_large_files != xno &&
+ test x$ac_cv_sys_large_files != xunknown; then
+ CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
+fi
+
+AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"])
+
+if test x$use_hardening != xno; then
+ AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"])
+ AX_CHECK_COMPILE_FLAG([-fPIE],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fPIE"])
+
+ AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2"])
+
+ AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"])
+ AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"])
+ AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [LDFLAGS="-Wl,-z,relro"])
+ AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [LDFLAGS="-Wl,-z,now"])
+
+ if test x$TARGET_OS != xwindows; then
+ # -fstack-protector-all can produce broken binaries with mingw
+ AX_CHECK_COMPILE_FLAG([-fno-stack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fno-stack-protector"])
+ AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"])
+
+ # -pie will link successfully with MinGW, but it's unsupported and leads to undeterministic binaries
+ AX_CHECK_LINK_FLAG([[-pie]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"])
+ fi
+
+ CXXFLAGS="$CXXFLAGS $HARDENED_CXXFLAGS"
+ CPPFLAGS="$CPPFLAGS $HARDENED_CPPFLAGS"
+ LDFLAGS="$LDFLAGS $HARDENED_LDFLAGS"
+ OBJCXXFLAGS="$CXXFLAGS"
+fi
+
+dnl this flag screws up non-darwin gcc even when the check fails. special-case it.
+if test x$TARGET_OS = xdarwin; then
+ AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"])
+fi
+
+AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h])
+
+dnl Check for MSG_NOSIGNAL
+AC_MSG_CHECKING(for MSG_NOSIGNAL)
+AC_TRY_COMPILE([#include <sys/socket.h>],
+ [ int f = MSG_NOSIGNAL; ],
+ [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MSG_NOSIGNAL, 1,[Define this symbol if you have MSG_NOSIGNAL]) ],
+ [ AC_MSG_RESULT(no)]
+)
+
+dnl Check for libdb_cxx
+BITCOIN_FIND_BDB48
+
+dnl Check for libminiupnpc (optional)
+if test x$use_upnp != xno; then
+ AC_CHECK_LIB([miniupnpc], [main],, [have_miniupnpc=no])
+fi
+
+dnl Check for boost libs
+AX_BOOST_BASE
+AX_BOOST_SYSTEM
+AX_BOOST_FILESYSTEM
+AX_BOOST_PROGRAM_OPTIONS
+AX_BOOST_THREAD
+AX_BOOST_CHRONO
+
+if test x$use_tests = xyes; then
+
+ if test x$HEXDUMP = x; then
+ AC_MSG_ERROR(hexdump is required for tests)
+ fi
+
+
+ AX_BOOST_UNIT_TEST_FRAMEWORK
+fi
+
+BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB"
+BOOST_INCLUDES="$BOOST_CPPFLAGS"
+
+dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however
+dnl it was broken from 1.50 to 1.52 when backed by nanosleep. Use sleep_for if
+dnl a working version is available, else fall back to sleep. sleep was removed
+dnl after 1.56.
+dnl If neither is available, abort.
+dnl If sleep_for is used, boost_chrono becomes a requirement.
+if test x$ax_cv_boost_chrono = xyes; then
+TEMP_LIBS="$LIBS"
+LIBS="$LIBS $BOOST_LIBS $BOOST_CHRONO_LIB"
+AC_TRY_LINK([
+ #include <boost/thread/thread.hpp>
+ #include <boost/version.hpp>
+ ],[
+ #if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(0));
+ #else
+ choke me
+ #endif
+ ],
+ [boost_sleep=yes; BOOST_LIBS="$BOOST_LIBS $BOOST_CHRONO_LIB";
+ AC_DEFINE(HAVE_WORKING_BOOST_SLEEP_FOR, 1, [Define this symbol if boost sleep_for works])],
+ [boost_sleep=no])
+LIBS="$TEMP_LIBS"
+fi
+
+if test x$boost_sleep != xyes; then
+TEMP_LIBS="$LIBS"
+LIBS="$LIBS $BOOST_LIBS"
+AC_TRY_LINK([
+ #include <boost/version.hpp>
+ #include <boost/thread.hpp>
+ #include <boost/date_time/posix_time/posix_time_types.hpp>
+ ],[
+ #if BOOST_VERSION <= 105600
+ boost::this_thread::sleep(boost::posix_time::milliseconds(0));
+ #else
+ choke me
+ #endif
+ ],
+ [boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP, 1, [Define this symbol if boost sleep works])],
+ [boost_sleep=no])
+LIBS="$TEMP_LIBS"
+fi
+
+if test x$boost_sleep != xyes; then
+ AC_MSG_ERROR(No working boost sleep implementation found)
+fi
+
+if test x$use_pkgconfig = xyes; then
+
+ if test x$PKG_CONFIG == x; then
+ AC_MSG_ERROR(pkg-config not found.)
+ fi
+
+ : #NOP
+ m4_ifdef(
+ [PKG_CHECK_MODULES],
+ [
+ PKG_CHECK_MODULES([SSL], [libssl], [INCLUDES="$INCLUDES $SSL_CFLAGS"; LIBS="$LIBS $SSL_LIBS"], [AC_MSG_ERROR(openssl not found.)])
+ PKG_CHECK_MODULES([CRYPTO], [libcrypto], [INCLUDES="$INCLUDES $CRYPTO_CFLAGS"; LIBS="$LIBS $CRYPTO_LIBS"], [AC_MSG_ERROR(libcrypto not found.)])
+
+ if test x$use_qt = xyes; then
+ PKG_CHECK_MODULES([QT], [QtCore QtGui QtNetwork], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes], [have_qt=no])
+ if test x$use_tests = xyes; then
+ PKG_CHECK_MODULES([QT_TEST], [QtTest], [QT_TEST_INCLUDES="$QT_TEST_CFLAGS"; have_qt_test=yes], [have_qt_test=no])
+ fi
+ if test x$use_dbus != xno; then
+ PKG_CHECK_MODULES([QT_DBUS], [QtDBus], [QT_DBUS_INCLUDES="$QT_DBUS_CFLAGS"; have_qt_dbus=yes], [have_qt_dbus=no])
+ fi
+ if test x$use_qr != xno; then
+ PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])
+ fi
+ PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [AC_MSG_ERROR(libprotobuf not found.)])
+ fi
+ ]
+ )
+else
+ AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing))
+ AC_CHECK_LIB([crypto], [main],, AC_MSG_ERROR(libcrypto missing))
+
+ AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),)
+ AC_CHECK_LIB([ssl], [main],, AC_MSG_ERROR(libssl missing))
+
+ if test x$use_qt = xyes; then
+ TEMP_LIBS="$LIBS"
+ LIBS=
+ if test x$qt_lib_path != x; then
+ QT_LIBS="$QT_LIBS -L$qt_lib_path"
+ LIBS="$QT_LIBS"
+ fi
+ if test x$qt_plugin_path != x; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/codecs"
+ LIBS="$QT_LIBS"
+ fi
+
+ if test x$TARGET_OS == xwindows; then
+ AC_CHECK_LIB([imm32], [main],, AC_MSG_ERROR(libimm32 not found. Install it or use --without-qt.))
+ fi
+
+ #TODO: These are only needed when they're linked directly to parent libs. It really has nothing to do with windows.
+ #Instead, check for missing functions in parent libs and assume static if they're absent.
+ if test x$TARGET_OS == xwindows; then
+ AC_CHECK_LIB([qcncodecs], [main],, AC_MSG_ERROR(libqcncodecs not found. Install it or use --without-qt.))
+ AC_CHECK_LIB([qjpcodecs], [main],, AC_MSG_ERROR(libqjpcodecs not found. Install it or use --without-qt.))
+ AC_CHECK_LIB([qkrcodecs], [main],, AC_MSG_ERROR(libqkrcodecs not found. Install it or use --without-qt.))
+ AC_CHECK_LIB([qtwcodecs], [main],, AC_MSG_ERROR(libqtwcodecs not found. Install it or use --without-qt.))
+ fi
+
+ AC_CHECK_LIB([QtCore], [main],, AC_MSG_ERROR(libQtCore not found. Install it or use --without-qt.))
+ AC_CHECK_LIB([QtGui], [main],, AC_MSG_ERROR(libQtGui not found. Install it or use --without-qt.))
+ AC_CHECK_LIB([QtNetwork], [main],, AC_MSG_ERROR(libQtNetwork not found. Install it or use --without-qt.))
+ AC_CHECK_LIB([protobuf], [main],, AC_MSG_ERROR(libprotobuf not found. Install it or use --without-qt.))
+ QT_LIBS="$LIBS"
+ LIBS="$TEMP_LIBS"
+
+ TEMP_CPPFLAGS="$CPPFLAGS"
+ if test x$qt_include_path != x; then
+ QT_INCLUDES="-I$qt_include_path -I$qt_include_path/QtCore -I$qt_include_path/QtGui -I$qt_include_path/QtNetwork -I$qt_include_path/QtTest -I$qt_include_path/QtDBus"
+ CPPFLAGS="$CPPFLAGS $QT_INCLUDES"
+ fi
+ AC_CHECK_HEADER([QtPlugin],, AC_MSG_ERROR(QtCore headers missing. Install them or use --without-qt.),)
+ AC_CHECK_HEADER([QApplication],, AC_MSG_ERROR(QtGUI headers missing. Install them or use --without-qt.),)
+ AC_CHECK_HEADER([QLocalSocket],, AC_MSG_ERROR(QtNetwork headers missing. Install them or use --without-qt.),)
+
+ if test x$use_tests = xyes; then
+ TEMP_LIBS="$LIBS"
+ LIBS=
+ if test x$qt_lib_path != x; then
+ LIBS="-L$qt_lib_path"
+ fi
+ AC_CHECK_LIB([QtTest], [main],, have_qt_test=no)
+ AC_CHECK_HEADER([QTest],, have_qt_test=no)
+ QT_TEST_LIBS="$LIBS"
+ LIBS="$TEMP_LIBS"
+ fi
+ if test x$use_dbus != xno; then
+ TEMP_LIBS="$LIBS"
+ LIBS=
+ if test x$qt_lib_path != x; then
+ LIBS="-L$qt_lib_path"
+ fi
+ AC_CHECK_LIB([QtDBus], [main],, have_qt_dbus=no)
+ AC_CHECK_HEADER([QtDBus],, have_qt_dbus=no)
+ QT_DBUS_LIBS="$LIBS"
+ LIBS="$TEMP_LIBS"
+ fi
+ CPPFLAGS="$TEMP_CPPFLAGS"
+ if test x$use_qr != xno; then
+ AC_CHECK_LIB([qrencode], [main],, [have_qrencode=no])
+ AC_CHECK_HEADER([qrencode.h],, have_qrencode=no)
+ fi
+ fi
+fi
+
+if test x$use_ipv6 = xyes; then
+ dnl Check for ipv6 build requirements
+ AC_MSG_CHECKING(for IPV6 build support)
+ AC_TRY_LINK([
+ #if defined(_WINDOWS)
+ #include <winsock2.h>
+ #else
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #endif
+ ],[
+ #if !defined(_WINDOWS)
+ struct in6_addr ipv6Addr;
+ struct sockaddr_in6 addr;
+ #endif
+ int temp = socket(AF_INET6, SOCK_STREAM, 0);],
+ [AC_MSG_RESULT(yes); have_ipv6=yes; AC_DEFINE(HAVE_IPV6, 1, [Define this symbol if you have ipv6 build support])],
+ [AC_MSG_RESULT(no)]; have_ipv6=no)
+fi
+AC_LANG_POP
+
+if test "x$use_ccache" != "xno"; then
+ AC_MSG_CHECKING(if ccache should be enabled)
+ if test x$CCACHE = x; then
+ if test "x$use_ccache" = "xyes"; then
+ AC_MSG_ERROR([ccache not found.]);
+ else
+ AC_MSG_NOTICE([ccache not found. Falling back to default CC])
+ use_ccache=no
+ fi
+ else
+ use_ccache=yes
+ CC="$ac_cv_path_CCACHE $CC"
+ CXX="$ac_cv_path_CCACHE $CXX"
+ fi
+ AC_MSG_RESULT($use_ccache)
+fi
+
+dnl enable ipv6 support
+AC_MSG_CHECKING([if ipv6 should be enabled])
+if test x$have_ipv6 = xno; then
+ if test x$use_ipv6 = xyes; then
+ AC_MSG_ERROR("ipv6 requested but cannot be built. use --disable-ipv6")
+ fi
+ AC_MSG_RESULT(no)
+else
+ if test x$use_ipv6 = xyes; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([USE_IPV6],[1],[Define if ipv6 support should be compiled in])
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+dnl enable upnp support
+AC_MSG_CHECKING([if upnp should be enabled])
+if test x$have_miniupnpc = xno; then
+ if test x$use_upnp = xyes; then
+ AC_MSG_ERROR("upnp requested but cannot be built. use --without-miniupnpc")
+ fi
+ AC_MSG_RESULT(no)
+else
+ if test x$use_upnp != xno; then
+ AC_MSG_RESULT(yes)
+ AC_MSG_CHECKING([if upnp should be on by default])
+ use_upnp=yes
+ upnp_setting=0
+ if test x$use_upnp_default != xno; then
+ use_upnp_default=yes
+ upnp_setting=1
+ fi
+ AC_MSG_RESULT($use_upnp_default)
+ AC_DEFINE_UNQUOTED([USE_UPNP],[$upnp_setting],[Define to 1 for upnp runtime support])
+ if test x$TARGET_OS = xwindows; then
+ CPPFLAGS="$CPPFLAGS -DSTATICLIB"
+ fi
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+dnl enable qt support
+AC_MSG_CHECKING([if qt should be enabled])
+if test x$use_qt = xyes; then
+ if test x$have_qt = xno; then
+ AC_MSG_ERROR("qt support requested but qt could not be located. use --without-qt")
+ fi
+ if test x$MOC = x; then
+ AC_MSG_ERROR("qt support requested but moc was not found. use --without-qt")
+ fi
+ if test x$PROTOC = x; then
+ AC_MSG_ERROR("qt support requested but protoc was not found. use --without-qt")
+ fi
+ if test x$UIC = x; then
+ AC_MSG_ERROR("qt support requested but uic was not found. use --without-qt")
+ fi
+ if test x$RCC = x; then
+ AC_MSG_ERROR("qt support requested but rcc was not found. use --without-qt")
+ fi
+ if test x$LRELEASE = x; then
+ AC_MSG_ERROR("qt support requested but lrelease was not found. use --without-qt")
+ fi
+ if test x$use_tests = xyes; then
+ if test x$have_qt_test = xno; then
+ AC_MSG_ERROR("libQtTest not found. Use --disable-tests or --without-qt.")
+ fi
+ fi
+ if test x$have_qt_dbus = xno; then
+ use_dbus=no
+ if test x$use_dbus = xyes; then
+ AC_MSG_ERROR("libQtDBus not found. Use --without-qtdbus.")
+ fi
+ fi
+ if test x$XGETTEXT == x; then
+ AC_MSG_WARN("xgettext is required to update qt translations")
+ fi
+ if test x$LUPDATE == x; then
+ AC_MSG_WARN("lupdate is required to update qt translations")
+ fi
+
+ BUILD_QT=qt
+else
+ use_qt=no
+fi
+
+AC_MSG_RESULT($use_qt)
+
+dnl these are only used when qt is enabled
+if test x$use_qt = xyes; then
+
+ dnl enable dbus support
+ AC_MSG_CHECKING([if dbus should be enabled])
+ if test x$use_dbus != xno; then
+ use_dbus=yes
+ AC_DEFINE([USE_DBUS],[1],[Define if dbus support should be compiled in])
+ else
+ use_dbus=no
+ fi
+ AC_MSG_RESULT($use_dbus)
+
+ dnl enable qr support
+ AC_MSG_CHECKING([if qr should be enabled])
+ if test x$have_qrencode = xno; then
+ if test x$use_qr == xyes; then
+ AC_MSG_ERROR("QR support requested but cannot be built. use --without-qrencode")
+ fi
+ AC_MSG_RESULT(no)
+ else
+ if test x$use_qr != xno; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([USE_QRCODE],[1],[Define if QR support should be compiled in])
+ use_qr=yes
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ if test x$use_tests = xyes; then
+ BUILD_TEST_QT="test"
+ fi
+fi
+
+if test x$use_tests = xyes; then
+ BUILD_TEST="test"
+fi
+
+AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
+AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
+AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
+AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes])
+AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno])
+
+AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
+AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
+AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision])
+AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build])
+AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release])
+AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Version is release])
+AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR)
+AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR)
+AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION)
+AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD)
+AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE)
+AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR)
+
+
+AC_SUBST(USE_UPNP)
+AC_SUBST(USE_QRCODE)
+AC_SUBST(USE_IPV6)
+AC_SUBST(INCLUDES)
+AC_SUBST(BOOST_LIBS)
+AC_SUBST(MOC_DEFS)
+AC_SUBST(QT_INCLUDES)
+AC_SUBST(QT_TEST_LIBS)
+AC_SUBST(QT_LIBS)
+AC_SUBST(QT_DBUS_LIBS)
+AC_SUBST(QT_DBUS_INCLUDES)
+AC_SUBST(QT_TEST_INCLUDES)
+AC_SUBST(TESTDEFS)
+AC_SUBST(LEVELDB_TARGET_FLAGS)
+AC_SUBST(BUILD_QT)
+AC_SUBST(BUILD_TEST)
+AC_SUBST(BUILD_TEST_QT)
+AC_CONFIG_FILES([Makefile src/Makefile src/test/Makefile src/qt/Makefile src/qt/test/Makefile share/setup.nsi share/qt/Info.plist])
+AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
+AC_CONFIG_FILES([qa/pull-tester/build-tests.sh],[chmod +x qa/pull-tester/build-tests.sh])
+AC_OUTPUT
diff --git a/contrib/README.md b/contrib/README.md
new file mode 100644
index 0000000000..7128fd5eb0
--- /dev/null
+++ b/contrib/README.md
@@ -0,0 +1,50 @@
+Contrib Index
+---------------------
+
+### [BitRPC](/contrib/bitrpc) ###
+Added bitrpc.py which allows for sending of all standard Bitcoin commands via RPC rather than as command line args.
+
+### [Debian](/contrib/debian) ###
+Contains files used to package bitcoind/bitcoin-qt
+for Debian-based Linux systems. If you compile bitcoind/bitcoin-qt yourself, there are some useful files here.
+
+### [Gitian-descriptors](/contrib/gitian-descriptors) ###
+Gavin's notes on getting gitian builds up and running using KVM.
+
+### [Gitian-downloader](/contrib/gitian-downloader)
+Various PGP files of core developers.
+
+### [Linearize](/contrib/linearize) ###
+Construct a linear, no-fork, best version of the blockchain.
+
+### [MacDeploy](/contrib/macdeploy) ###
+Scripts and notes for Mac builds.
+
+### [PyMiner](/contrib/pyminer) ###
+
+This is a 'getwork' CPU mining client for Bitcoin. It is pure-python, and therefore very, very slow. The purpose is to provide a reference implementation of a miner, for study.
+
+### [Qos](/contrib/qos) ###
+
+A Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Bitcoin network. This means one can have an always-on bitcoind instance running, and another local bitcoind/bitcoin-qt instance which connects to this node and receives blocks from it.
+
+### [Seeds](/contrib/seeds) ###
+Utility to generate the pnSeed[] array that is compiled into the client.
+
+### [SpendFrom](/contrib/spendfrom) ###
+
+Use the raw transactions API to send coins received on a particular
+address (or addresses).
+
+### [TestGen](/contrib/testgen) ###
+Utilities to generate test vectors for the data-driven Bitcoin tests.
+
+### [Test Patches](/contrib/test-patches) ###
+These patches are applied when the automated pull-tester
+tests each pull and when master is tested using jenkins.
+
+### [Verify SF Binaries](/contrib/verifysfbinaries) ###
+This script attempts to download and verify the signature file SHA256SUMS.asc from SourceForge.
+
+### [Wallet Tools](/contrib/wallettools) ###
+Contains a wallet change password and unlock script.
diff --git a/contrib/bitcoin-qt.pro b/contrib/bitcoin-qt.pro
new file mode 100644
index 0000000000..0b181ef449
--- /dev/null
+++ b/contrib/bitcoin-qt.pro
@@ -0,0 +1,17 @@
+FORMS += \
+ ../src/qt/forms/transactiondescdialog.ui \
+ ../src/qt/forms/signverifymessagedialog.ui \
+ ../src/qt/forms/sendcoinsentry.ui \
+ ../src/qt/forms/sendcoinsdialog.ui \
+ ../src/qt/forms/rpcconsole.ui \
+ ../src/qt/forms/qrcodedialog.ui \
+ ../src/qt/forms/overviewpage.ui \
+ ../src/qt/forms/optionsdialog.ui \
+ ../src/qt/forms/intro.ui \
+ ../src/qt/forms/editaddressdialog.ui \
+ ../src/qt/forms/askpassphrasedialog.ui \
+ ../src/qt/forms/addressbookpage.ui \
+ ../src/qt/forms/aboutdialog.ui
+
+RESOURCES += \
+ ../src/qt/bitcoin.qrc
diff --git a/contrib/bitrpc/README.md b/contrib/bitrpc/README.md
new file mode 100644
index 0000000000..2dde60a08e
--- /dev/null
+++ b/contrib/bitrpc/README.md
@@ -0,0 +1,2 @@
+### BitRPC ###
+Allows for sending of all standard Bitcoin commands via RPC rather than as command line args. \ No newline at end of file
diff --git a/contrib/debian/README b/contrib/debian/README
deleted file mode 100644
index 1cb9b75fbd..0000000000
--- a/contrib/debian/README
+++ /dev/null
@@ -1,20 +0,0 @@
-This directory contains files used to package bitcoind/bitcoin-qt
-for Debian-based Linux systems.
-
-If you compile bitcoind/bitcoin-qt yourself, there are some
-useful files here:
-
-bitcoin: URI support
---------------------
-
-bitcoin-qt.desktop (Gnome / Open Desktop)
-To install:
- sudo desktop-file-install bitcoin-qt.desktop
- sudo update-desktop-database
-
-If you build yourself, you will either need to modify the paths in
-the .desktop file or copy or symlink your bitcoin-qt binary to /usr/bin
-and the ../../share/pixmaps/bitcoin128.png to /usr/share/pixmaps
-
-bitcoin-qt.protocol (KDE)
-
diff --git a/contrib/debian/README.md b/contrib/debian/README.md
new file mode 100644
index 0000000000..fab9cc2381
--- /dev/null
+++ b/contrib/debian/README.md
@@ -0,0 +1,21 @@
+
+Debian
+====================
+This directory contains files used to package bitcoind/bitcoin-qt
+for Debian-based Linux systems. If you compile bitcoind/bitcoin-qt yourself, there are some useful files here.
+
+## bitcoin: URI support ##
+
+
+bitcoin-qt.desktop (Gnome / Open Desktop)
+To install:
+
+ sudo desktop-file-install bitcoin-qt.desktop
+ sudo update-desktop-database
+
+If you build yourself, you will either need to modify the paths in
+the .desktop file or copy or symlink your bitcoin-qt binary to `/usr/bin`
+and the `../../share/pixmaps/bitcoin128.png` to `/usr/share/pixmaps`
+
+bitcoin-qt.protocol (KDE)
+
diff --git a/contrib/debian/bitcoin-qt.desktop b/contrib/debian/bitcoin-qt.desktop
index b2a2cef622..82bc80a734 100644
--- a/contrib/debian/bitcoin-qt.desktop
+++ b/contrib/debian/bitcoin-qt.desktop
@@ -9,4 +9,4 @@ Terminal=false
Type=Application
Icon=/usr/share/pixmaps/bitcoin128.png
MimeType=x-scheme-handler/bitcoin;
-Categories=Office;
+Categories=Office;Finance;
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
index e600e46705..bd6b42dc51 100644
--- a/contrib/debian/changelog
+++ b/contrib/debian/changelog
@@ -1,3 +1,27 @@
+bitcoin (0.8.5-precise1) precise; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo <matt@bluematt.me> Sun, 15 Sep 2013 14:02:00 -0400
+
+bitcoin (0.8.4-precise1) precise; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo <matt@bluematt.me> Wed, 4 Sep 2013 10:25:00 -0400
+
+bitcoin (0.8.3-natty1) natty; urgency=low
+
+ * New upstream release.
+
+ -- Matt Corallo <matt@bluematt.me> Wed, 26 Jun 2013 00:18:00 +0100
+
+bitcoin (0.8.2-natty1) natty; urgency=low
+
+ * New upstream release.
+
+ -- Matt Corallo <matt@bluematt.me> Wed, 29 Mar 2013 23:23:00 +0100
+
bitcoin (0.8.1-natty3) natty; urgency=low
* New pixmaps
diff --git a/contrib/gitian-descriptors/README b/contrib/gitian-descriptors/README.md
index f1c960ba11..40bdbd8e32 100644
--- a/contrib/gitian-descriptors/README
+++ b/contrib/gitian-descriptors/README.md
@@ -1,7 +1,7 @@
-Gavin's notes on getting gitian builds up and running using KVM:
+### Gavin's notes on getting gitian builds up and running using KVM:###
These instructions distilled from:
- https://help.ubuntu.com/community/KVM/Installation
+[ https://help.ubuntu.com/community/KVM/Installation]( https://help.ubuntu.com/community/KVM/Installation)
... see there for complete details.
You need the right hardware: you need a 64-bit-capable CPU with hardware virtualization support (Intel VT-x or AMD-V). Not all modern CPUs support hardware virtualization.
@@ -9,11 +9,13 @@ You need the right hardware: you need a 64-bit-capable CPU with hardware virtual
You probably need to enable hardware virtualization in your machine's BIOS.
You need to be running a recent version of 64-bit-Ubuntu, and you need to install several prerequisites:
- sudo apt-get install ruby apache2 git apt-cacher-ng python-vm-builder qemu-kvm
+
+ sudo apt-get install ruby apache2 git apt-cacher-ng python-vm-builder qemu-kvm
Sanity checks:
- sudo service apt-cacher-ng status # Should return apt-cacher-ng is running
- ls -l /dev/kvm # Should show a /dev/kvm device
+
+ sudo service apt-cacher-ng status # Should return apt-cacher-ng is running
+ ls -l /dev/kvm # Should show a /dev/kvm device
Once you've got the right hardware and software:
@@ -22,16 +24,18 @@ Once you've got the right hardware and software:
git clone git://github.com/devrandom/gitian-builder.git
mkdir gitian-builder/inputs
cd gitian-builder/inputs
+
# Inputs for Linux and Win32:
wget -O miniupnpc-1.6.tar.gz 'http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.6.tar.gz'
wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2'
- # Inputs for Win32: (Linux has packages for these)
+
+ # Inputs for Win32: (Linux has packages for these)
wget 'https://downloads.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2'
wget 'http://www.openssl.org/source/openssl-1.0.1c.tar.gz'
wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
wget 'https://downloads.sourceforge.net/project/libpng/zlib/1.2.6/zlib-1.2.6.tar.gz'
wget 'https://downloads.sourceforge.net/project/libpng/libpng15/older-releases/1.5.9/libpng-1.5.9.tar.gz'
- wget 'http://releases.qt-project.org/qt4/source/qt-everywhere-opensource-src-4.8.3.tar.gz'
+ wget 'https://download.qt-project.org/archive/qt/4.8/4.8.3/qt-everywhere-opensource-src-4.8.3.tar.gz'
wget 'http://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2'
cd ../..
@@ -58,31 +62,29 @@ Once you've got the right hardware and software:
---------------------
-gitian-builder now also supports building using LXC. See
- https://help.ubuntu.com/12.04/serverguide/lxc.html
+`gitian-builder` now also supports building using LXC. See
+[ https://help.ubuntu.com/12.04/serverguide/lxc.html]( https://help.ubuntu.com/12.04/serverguide/lxc.html)
... for how to get LXC up and running under Ubuntu.
If your main machine is a 64-bit Mac or PC with a few gigabytes of memory
-and at least 10 gigabytes of free disk space, you can gitian-build using
+and at least 10 gigabytes of free disk space, you can `gitian-build` using
LXC running inside a virtual machine.
Here's a description of Gavin's setup on OSX 10.6:
-1. Download and install VirtualBox from https://www.virtualbox.org/
+1. Download and install VirtualBox from [https://www.virtualbox.org/](https://www.virtualbox.org/)
2. Download the 64-bit Ubuntu Desktop 12.04 LTS .iso CD image from
- http://www.ubuntu.com/
+ [http://www.ubuntu.com/](http://www.ubuntu.com/)
-3. Run VirtualBox and create a new virtual machine, using the
- Ubuntu .iso (see the VirtualBox documentation for details).
- Create it with at least 2 gigabytes of memory and a disk
- that is at least 20 gigabytes big.
+3. Run VirtualBox and create a new virtual machine, using the Ubuntu .iso (see the [VirtualBox documentation](https://www.virtualbox.org/wiki/Documentation) for details). Create it with at least 2 gigabytes of memory and a disk that is at least 20 gigabytes big.
4. Inside the running Ubuntu desktop, install:
- sudo apt-get install debootstrap lxc ruby apache2 git apt-cacher-ng python-vm-builder
-5. Still inside Ubuntu, tell gitian-builder to use LXC, then follow the "Once you've got the right
- hardware and software" instructions above:
- export USE_LXC=1
- git clone git://github.com/bitcoin/bitcoin.git
- ... etc
+ sudo apt-get install debootstrap lxc ruby apache2 git apt-cacher-ng python-vm-builder
+
+5. Still inside Ubuntu, tell gitian-builder to use LXC, then follow the "Once you've got the right hardware and software" instructions above:
+
+ export USE_LXC=1
+ git clone git://github.com/bitcoin/bitcoin.git
+ ... etc \ No newline at end of file
diff --git a/contrib/gitian-descriptors/boost-win32.yml b/contrib/gitian-descriptors/boost-win32.yml
index 1eeb9eaa28..b421cbe8c5 100644
--- a/contrib/gitian-descriptors/boost-win32.yml
+++ b/contrib/gitian-descriptors/boost-win32.yml
@@ -1,38 +1,66 @@
---
name: "boost"
suites:
-- "lucid"
+- "precise"
architectures:
-- "i386"
-packages:
-- "mingw32"
+- "amd64"
+packages:
+- "mingw-w64"
+- "g++-mingw-w64"
- "faketime"
- "zip"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
-- "boost_1_50_0.tar.bz2"
+- "boost_1_54_0.tar.bz2"
+- "boost-mingw-gas-cross-compile-2013-03-03.patch"
script: |
- TMPDIR="$HOME/tmpdir"
- mkdir -p $TMPDIR/bin/$GBUILD_BITS $TMPDIR/include
- tar xjf boost_1_50_0.tar.bz2
- cd boost_1_50_0
- echo "using gcc : 4.4 : i586-mingw32msvc-g++
+ # Defines
+ INSTALLPREFIX="$OUTDIR/staging/boost"
+ HOST=i686-w64-mingw32
+ # Input Integrity Check
+ echo "047e927de336af106a24bceba30069980c191529fd76b8dff8eb9a328b48ae1d boost_1_54_0.tar.bz2" | shasum -c
+ echo "d2b7f6a1d7051faef3c9cf41a92fa3671d905ef1e1da920d07651a43299f6268 boost-mingw-gas-cross-compile-2013-03-03.patch" | shasum -c
+
+ mkdir -p "$INSTALLPREFIX"
+ tar xjf boost_1_54_0.tar.bz2
+ cd boost_1_54_0
+ GCCVERSION=$($HOST-g++ -E -dM $(mktemp --suffix=.h) | grep __VERSION__ | cut -d ' ' -f 3 | cut -d '"' -f 2)
+ echo "using gcc : $GCCVERSION : $HOST-g++
:
- <rc>i586-mingw32msvc-windres
- <archiver>i586-mingw32msvc-ar
+ <rc>$HOST-windres
+ <archiver>$HOST-ar
<cxxflags>-frandom-seed=boost1
+ <ranlib>$HOST-ranlib
;" > user-config.jam
./bootstrap.sh --without-icu
- ./bjam toolset=gcc target-os=windows threadapi=win32 threading=multi variant=release link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete $MAKEOPTS stage
- for lib in chrono date_time exception filesystem graph iostreams math_c99f math_c99l math_c99 math_tr1f math_tr1l math_tr1 prg_exec_monitor program_options random regex serialization signals system test_exec_monitor thread_win32 unit_test_framework wave wserialization; do
- mkdir $lib
- (cd $lib ; ar xf ../stage/lib/libboost_${lib}-mt-s.a)
- mv $lib $TMPDIR/bin/$GBUILD_BITS
- done
- cp -a boost $TMPDIR/include
- cd $TMPDIR
+
+ # Workaround: Upstream boost dev refuses to include patch that would allow Free Software cross-compile toolchain to work
+ # This patch was authored by the Fedora package developer and ships in Fedora's mingw32-boost.
+ # Please obtain the exact patch that matches the above sha256sum from one of the following mirrors.
+ #
+ # Read History: https://svn.boost.org/trac/boost/ticket/7262
+ # History Mirror: http://rose.makesad.us/~paulproteus/mirrors/7262%20Boost.Context%20fails%20to%20build%20using%20MinGW.html
+ #
+ # Patch: https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch
+ # Patch Mirror: http://wtogami.fedorapeople.org/boost-mingw-gas-cross-compile-2013-03-03.patch
+ # Patch Mirror: http://mindstalk.net/host/boost-mingw-gas-cross-compile-2013-03-03.patch
+ # Patch Mirror: http://rose.makesad.us/~paulproteus/mirrors/boost-mingw-gas-cross-compile-2013-03-03.patch
+ patch -p0 < ../boost-mingw-gas-cross-compile-2013-03-03.patch
+
+ # Bug Workaround: boost-1.54.0 broke the ability to disable zlib
+ # https://svn.boost.org/trac/boost/ticket/9156
+ sed -i 's^\[ ac.check-library /zlib//zlib : <library>/zlib//zlib^^' libs/iostreams/build/Jamfile.v2
+ sed -i 's^<source>zlib.cpp <source>gzip.cpp \]^^' libs/iostreams/build/Jamfile.v2
+
+ # http://statmt.org/~s0565741/software/boost_1_52_0/libs/context/doc/html/context/requirements.html
+ # Note: Might need these options in the future for 64bit builds.
+ # "Please note that address-model=64 must be given to bjam command line on 64bit Windows for 64bit build; otherwise 32bit code will be generated."
+ # "For cross-compiling the lib you must specify certain additional properties at bjam command line: target-os, abi, binary-format, architecture and address-model."
+ ./bjam toolset=gcc binary-format=pe target-os=windows threadapi=win32 threading=multi variant=release link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete --prefix="$INSTALLPREFIX" $MAKEOPTS install
+
+ cd "$INSTALLPREFIX"
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
- zip -r boost-win32-1.50.0-gitian2.zip *
- cp boost-win32-1.50.0-gitian2.zip $OUTDIR
+ zip -r boost-win32-1.54.0-gitian-r6.zip *
+ cp boost-win32-1.54.0-gitian-r6.zip $OUTDIR
diff --git a/contrib/gitian-descriptors/deps-win32.yml b/contrib/gitian-descriptors/deps-win32.yml
index 90f4c6c4be..7ad00fcb01 100644
--- a/contrib/gitian-descriptors/deps-win32.yml
+++ b/contrib/gitian-descriptors/deps-win32.yml
@@ -1,15 +1,15 @@
---
name: "bitcoin-deps"
suites:
-- "lucid"
+- "precise"
architectures:
-- "i386"
+- "amd64"
packages:
-- "mingw32"
+- "mingw-w64"
+- "g++-mingw-w64"
- "git-core"
- "zip"
- "faketime"
-- "wine"
- "psmisc"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
@@ -25,48 +25,69 @@ script: |
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
export TZ=UTC
+ export INSTALLPREFIX=$OUTDIR/staging/deps
+ export HOST=i686-w64-mingw32
#
+ mkdir -p $INSTALLPREFIX
+
tar xzf openssl-1.0.1c.tar.gz
cd openssl-1.0.1c
- ./Configure --cross-compile-prefix=i586-mingw32msvc- mingw
+ ./Configure --cross-compile-prefix=$HOST- mingw --openssldir=$INSTALLPREFIX
make
+ make install_sw
cd ..
#
tar xzf db-4.8.30.NC.tar.gz
cd db-4.8.30.NC/build_unix
- ../dist/configure --enable-mingw --enable-cxx --host=i586-mingw32msvc CFLAGS="-I/usr/i586-mingw32msvc/include"
- make $MAKEOPTS
+ ../dist/configure --prefix=$INSTALLPREFIX --enable-mingw --enable-cxx --host=$HOST --disable-shared
+ make $MAKEOPTS library_build
+ make install_lib install_include
cd ../..
#
tar xzf miniupnpc-1.6.tar.gz
cd miniupnpc-1.6
- sed 's/dllwrap -k --driver-name gcc/$(DLLWRAP) -k --driver-name $(CC)/' -i Makefile.mingw
- sed 's|wingenminiupnpcstrings $< $@|./wingenminiupnpcstrings $< $@|' -i Makefile.mingw
- make -f Makefile.mingw DLLWRAP=i586-mingw32msvc-dllwrap CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar
+ echo "
+ --- miniupnpc-1.6/Makefile.mingw.orig 2013-09-29 18:52:51.014087958 -1000
+ +++ miniupnpc-1.6/Makefile.mingw 2013-09-29 19:09:29.663318691 -1000
+ @@ -67,8 +67,8 @@
+
+ wingenminiupnpcstrings.o: wingenminiupnpcstrings.c
+
+ -miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings
+ - wingenminiupnpcstrings \$< \$@
+ +miniupnpcstrings.h: miniupnpcstrings.h.in
+ + sed -e 's|OS/version|MSWindows/5.1.2600|' -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"VERSIONHERE\"|' \$< > \$@
+
+ minixml.o: minixml.c minixml.h miniupnpcstrings.h
+
+ " | sed "s/VERSIONHERE/$(cat VERSION)/" | patch -p1
+ mkdir -p dll
+ make -f Makefile.mingw CC=$HOST-gcc AR=$HOST-ar libminiupnpc.a
+ install -d $INSTALLPREFIX/include/miniupnpc
+ install *.h $INSTALLPREFIX/include/miniupnpc
+ install libminiupnpc.a $INSTALLPREFIX/lib
cd ..
- mv miniupnpc-1.6 miniupnpc
#
tar xzf zlib-1.2.6.tar.gz
cd zlib-1.2.6
- make -f win32/Makefile.gcc PREFIX=i586-mingw32msvc- $MAKEOPTS
+ CROSS_PREFIX=$HOST- ./configure --prefix=$INSTALLPREFIX --static
+ make
+ make install
cd ..
#
tar xzf libpng-1.5.9.tar.gz
cd libpng-1.5.9
- ./configure -disable-shared CC=i586-mingw32msvc-cc AR=i586-mingw32msvc-ar STRIP=i586-mingw32msvc-strip RANLIB=i586-mingw32msvc-ranlib OBJDUMP=i586-mingw32msvc-objdump LD=i586-mingw32msvc-ld LDFLAGS="-L../zlib-1.2.6/" CFLAGS="-I../zlib-1.2.6/"
+ CFLAGS="-I$INSTALLPREFIX/include" LDFLAGS="-L$INSTALLPREFIX/lib" ./configure --disable-shared --prefix=$INSTALLPREFIX --host=$HOST
make $MAKEOPTS
+ make install
cd ..
#
tar xjf qrencode-3.2.0.tar.bz2
cd qrencode-3.2.0
- ./configure CC=i586-mingw32msvc-cc AR=i586-mingw32msvc-ar STRIP=i586-mingw32msvc-strip RANLIB=i586-mingw32msvc-ranlib OBJDUMP=i586-mingw32msvc-objdump LD=i586-mingw32msvc-ld png_LIBS="../libpng-1.5.9/.libs/libpng15.a ../zlib-1.2.6/libz.a" png_CFLAGS="-I../libpng-1.5.9"
- make $MAKEOPTS
+ png_CFLAGS="-I$INSTALLPREFIX/include" png_LIBS="-L$INSTALLPREFIX/lib -lpng" ./configure --prefix=$INSTALLPREFIX --host=$HOST
+ make
+ make install
cd ..
#
- zip -r $OUTDIR/bitcoin-deps-0.0.5.zip \
- $(ls qrencode-*/{qrencode.h,.libs/libqrencode.{,l}a} | sort) \
- $(ls db-*/build_unix/{libdb_cxx.a,db.h,db_cxx.h,libdb.a,.libs/libdb_cxx-?.?.a} | sort) \
- $(find openssl-* -name '*.a' -o -name '*.h' | sort) \
- $(find miniupnpc -name '*.h' -o -name 'libminiupnpc.a' | sort)
- # Kill wine processes as gitian won't figure out we are done otherwise
- killall wineserver services.exe explorer.exe winedevice.exe
+ cd $INSTALLPREFIX
+ zip -r $OUTDIR/bitcoin-deps-win32-gitian-r9.zip include lib
diff --git a/contrib/gitian-descriptors/gitian-win32.yml b/contrib/gitian-descriptors/gitian-win32.yml
index 5fc5a5a16b..a8a823cac0 100644
--- a/contrib/gitian-descriptors/gitian-win32.yml
+++ b/contrib/gitian-descriptors/gitian-win32.yml
@@ -1,78 +1,61 @@
---
name: "bitcoin"
suites:
-- "lucid"
+- "precise"
architectures:
-- "i386"
+- "amd64"
packages:
-- "mingw32"
+- "mingw-w64"
+- "g++-mingw-w64"
- "git-core"
- "unzip"
- "nsis"
- "faketime"
-reference_datetime: "2011-01-30 00:00:00"
+- "autoconf2.13"
+- "libtool"
+- "automake"
+- "pkg-config"
+- "bsdmainutils"
+
+reference_datetime: "2013-06-01 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
files:
-- "qt-win32-4.8.3-gitian-r2.zip"
-- "boost-win32-1.50.0-gitian2.zip"
-- "bitcoin-deps-0.0.5.zip"
-- "protobuf-win32-2.5.0-gitian-r1.zip"
+- "qt-win32-4.8.3-gitian-r4.zip"
+- "boost-win32-1.54.0-gitian-r6.zip"
+- "bitcoin-deps-win32-gitian-r9.zip"
+- "protobuf-win32-2.5.0-gitian-r3.zip"
script: |
#
- export QTDIR=$HOME/qt
- mkdir $QTDIR
- cd $QTDIR
- unzip ../build/qt-win32-4.8.3-gitian-r2.zip
- cd $HOME/build/
- export PATH=$QTDIR/bin/:$PATH
- #
- mkdir boost_1_50_0
- cd boost_1_50_0
- mkdir -p stage/lib
- unzip ../boost-win32-1.50.0-gitian2.zip
- cd bin/$GBUILD_BITS
- for lib in *; do
- i586-mingw32msvc-ar rc ../../stage/lib/libboost_${lib}-mt-s.a $lib/*.o
- i586-mingw32msvc-ranlib ../../stage/lib/libboost_${lib}-mt-s.a
- done
- cd ../..
- mv include/boost .
- cd ..
- #
- unzip bitcoin-deps-0.0.5.zip
+ STAGING=$HOME/staging
+ HOST=i686-w64-mingw32
#
- unzip protobuf-win32-2.5.0-gitian-r1.zip
- #
- find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p $STAGING
+ cd $STAGING
+ unzip ../build/qt-win32-4.8.3-gitian-r4.zip
+ unzip ../build/boost-win32-1.54.0-gitian-r6.zip
+ unzip ../build/bitcoin-deps-win32-gitian-r9.zip
+ unzip ../build/protobuf-win32-2.5.0-gitian-r3.zip
+ cd $HOME/build/
#
cd bitcoin
- mkdir -p $OUTDIR/src
- git archive HEAD | tar -x -C $OUTDIR/src
- cp $OUTDIR/src/doc/README_windows.txt $OUTDIR/readme.txt
- cp $OUTDIR/src/COPYING $OUTDIR/COPYING.txt
+ export PATH=$STAGING/host/bin:$PATH
+ export TAR_OPTIONS=--mtime=`echo $REFERENCE_DATETIME | awk '{ print $1 }'`
+ ./autogen.sh
+ ./configure --bindir=$OUTDIR --prefix=$STAGING --host=$HOST --with-qt-plugindir=$STAGING/plugins --with-qt-incdir=$STAGING/include --with-qt-bindir=$STAGING/host/bin --with-boost=$STAGING --disable-maintainer-mode --with-protoc-bindir=$STAGING/host/bin --disable-dependency-tracking CPPFLAGS="-I$STAGING/include" LDFLAGS="-L$STAGING/lib" CXXFLAGS="-frandom-seed=bitcoin"
+ make dist
+ mkdir -p distsrc
+ cd distsrc
+ tar --strip-components=1 -xf ../bitcoin-*.tar.*
+ ./configure --bindir=$OUTDIR --prefix=$STAGING --host=i686-w64-mingw32 --with-qt-plugindir=$STAGING/plugins --with-qt-incdir=$STAGING/include --with-qt-bindir=$STAGING/host/bin --with-boost=$STAGING --disable-maintainer-mode --with-protoc-bindir=$STAGING/host/bin --disable-dependency-tracking CPPFLAGS="-I$STAGING/include" LDFLAGS="-L$STAGING/lib" CXXFLAGS="-frandom-seed=bitcoin"
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
export TZ=UTC
- $QTDIR/bin/qmake -spec unsupported/win32-g++-cross PROTOBUF_LIB_PATH=$HOME/build/protobuf-win32 PROTOBUF_INCLUDE_PATH=$HOME/build/protobuf-win32 PROTOC=$HOME/build/protobuf-win32/protoc MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_50_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_50_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1c OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1c/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1
make $MAKEOPTS
- cp release/bitcoin-qt.exe $OUTDIR/
- #
- cd src
- export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
- export FAKETIME=$REFERENCE_DATETIME
- export TZ=UTC
- make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_UPNP=0 DEBUGFLAGS="-frandom-seed=bitcoin"
- i586-mingw32msvc-strip bitcoind.exe
- mkdir $OUTDIR/daemon
- cp bitcoind.exe $OUTDIR/daemon
- cd ..
- mkdir nsis
- git archive HEAD | tar -x -C nsis
- cd nsis/src
- mkdir ../release
- cp ../../release/* ../release/
- cp ../../src/*.exe .
- makensis ../share/setup.nsi
- cp ../share/bitcoin-*-win32-setup.exe $OUTDIR/
+ make deploy
+ make install-strip
+ cp -f bitcoin-*setup*.exe $OUTDIR/
+
+ mkdir -p $OUTDIR/src
+ cp -f ../bitcoin-*.tar.* $OUTDIR/src
diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml
index 6d47a46d5a..18e4cc2803 100644
--- a/contrib/gitian-descriptors/gitian.yml
+++ b/contrib/gitian-descriptors/gitian.yml
@@ -13,11 +13,17 @@ packages:
- "libboost-filesystem-dev"
- "libboost-program-options-dev"
- "libboost-thread-dev"
+- "libboost-test-dev"
- "libssl-dev"
- "git-core"
- "unzip"
- "pkg-config"
- "libpng12-dev"
+- "autoconf2.13"
+- "libtool"
+- "automake"
+- "faketime"
+- "bsdmainutils"
reference_datetime: "2013-06-01 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
@@ -27,35 +33,38 @@ files:
- "qrencode-3.2.0.tar.bz2"
- "protobuf-2.5.0.tar.bz2"
script: |
- INSTDIR="$HOME/install"
- export LIBRARY_PATH="$INSTDIR/lib"
+ STAGING="$HOME/install"
+ export LIBRARY_PATH="$STAGING/lib"
#
tar xzfm miniupnpc-1.6.tar.gz
cd miniupnpc-1.6
- INSTALLPREFIX=$INSTDIR make $MAKEOPTS install
+ INSTALLPREFIX=$STAGING make $MAKEOPTS install
cd ..
#
tar xjfm qrencode-3.2.0.tar.bz2
cd qrencode-3.2.0
- ./configure --prefix=$INSTDIR --enable-static --disable-shared
+ sed -i 's/@LIBPTHREAD@//' libqrencode.pc.in
+ ./configure --prefix=$STAGING --enable-static --disable-shared
make $MAKEOPTS install
cd ..
#
tar xjfm protobuf-2.5.0.tar.bz2
cd protobuf-2.5.0
- ./configure --prefix=$INSTDIR --enable-static --disable-shared
+ mkdir -p $STAGING/host/bin
+ ./configure --prefix=$STAGING --bindir=$STAGING/host/bin --enable-static --disable-shared
make $MAKEOPTS install
cd ..
#
cd bitcoin
- mkdir -p $OUTDIR/src
- git archive HEAD | tar -x -C $OUTDIR/src
- cp $OUTDIR/src/doc/README.md $OUTDIR
- cp $OUTDIR/src/COPYING $OUTDIR
- mkdir -p $OUTDIR/bin/$GBUILD_BITS
- qmake INCLUDEPATH="$INSTDIR/include" LIBS="-L$INSTDIR/lib" PROTOC="$INSTDIR/bin/protoc" PROTOBUF_LIB_PATH="$INSTDIR/lib" PROTOBUF_INCLUDE_PATH="$INSTDIR/include" RELEASE=1 USE_QRCODE=1
+ export TAR_OPTIONS=--mtime=`echo $REFERENCE_DATETIME | awk '{ print $1 }'`
+ ./autogen.sh
+ ./configure --prefix=$STAGING --bindir=$OUTDIR --with-protoc-bindir=$STAGING/host/bin --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include" LDFLAGS="-L$STAGING/lib" CXXFLAGS="-frandom-seed=bitcoin"
+ make dist
+ mkdir -p distsrc
+ cd distsrc
+ tar --strip-components=1 -xf ../bitcoin-*.tar.*
+ ./configure --prefix=$STAGING --bindir=$OUTDIR --with-protoc-bindir=$STAGING/host/bin --disable-maintainer-mode --disable-dependency-tracking PKG_CONFIG_PATH="$STAGING/lib/pkgconfig" CPPFLAGS="-I$STAGING/include" LDFLAGS="-L$STAGING/lib" CXXFLAGS="-frandom-seed=bitcoin"
make $MAKEOPTS
- install bitcoin-qt $OUTDIR/bin/$GBUILD_BITS
- cd src
- make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 DEBUGFLAGS=
- install -s bitcoind $OUTDIR/bin/$GBUILD_BITS
+ make $MAKEOPTS install-strip
+ mkdir -p $OUTDIR/src
+ cp ../bitcoin-*.tar.* $OUTDIR/src
diff --git a/contrib/gitian-descriptors/protobuf-win32.yml b/contrib/gitian-descriptors/protobuf-win32.yml
index 492b21e7f5..35f261e1a2 100644
--- a/contrib/gitian-descriptors/protobuf-win32.yml
+++ b/contrib/gitian-descriptors/protobuf-win32.yml
@@ -1,11 +1,12 @@
---
name: "protobuf-win32"
suites:
-- "lucid"
+- "precise"
architectures:
-- "i386"
+- "amd64"
packages:
-- "mingw32"
+- "mingw-w64"
+- "g++-mingw-w64"
- "zip"
- "faketime"
reference_datetime: "2013-04-15 00:00:00"
@@ -14,24 +15,28 @@ files:
- "protobuf-2.5.0.tar.bz2"
script: |
#
- export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
- export FAKETIME=$REFERENCE_DATETIME
export TZ=UTC
+ export INSTALLPREFIX=$OUTDIR/staging/deps
+ export HOST=i686-w64-mingw32
+ #
#
+ mkdir -p $INSTALLPREFIX
+
tar xjf protobuf-2.5.0.tar.bz2
cd protobuf-2.5.0
# First: build a native (linux) protoc
./configure --enable-shared=no --disable-dependency-tracking
make
- mkdir -p host
- cp src/protoc host
+ mkdir -p $INSTALLPREFIX/host/bin
+ cp src/protoc $INSTALLPREFIX/host/bin
# Now recompile with the mingw cross-compiler:
make distclean
- ./configure --enable-shared=no --disable-dependency-tracking --with-protoc=$(pwd)/host/protoc --host=i586-mingw32msvc CXXFLAGS=-frandom-seed=11
+ ./configure --prefix=$INSTALLPREFIX --enable-shared=no --disable-dependency-tracking --with-protoc=$INSTALLPREFIX/host/bin/protoc --host=$HOST CXXFLAGS=-frandom-seed=11
make
- cd ..
- mkdir -p protobuf-win32
- cp protobuf-2.5.0/host/protoc protobuf-win32/protoc
- cp protobuf-2.5.0/src/.libs/libprotobuf.a protobuf-win32/libprotobuf.a
- cp -r protobuf-2.5.0/src/google protobuf-win32/
- zip -r $OUTDIR/protobuf-win32-2.5.0-gitian-r1.zip protobuf-win32
+ make install
+ cd $INSTALLPREFIX
+ export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
+ export FAKETIME=$REFERENCE_DATETIME
+ zip -r $OUTDIR/protobuf-win32-2.5.0-gitian-r3.zip include lib host
+ unset LD_PRELOAD
+ unset FAKETIME
diff --git a/contrib/gitian-descriptors/qt-win32.yml b/contrib/gitian-descriptors/qt-win32.yml
index 7152875b86..1fc6f861e0 100644
--- a/contrib/gitian-descriptors/qt-win32.yml
+++ b/contrib/gitian-descriptors/qt-win32.yml
@@ -1,50 +1,57 @@
---
name: "qt"
suites:
-- "lucid"
+- "precise"
architectures:
-- "i386"
+- "amd64"
packages:
-- "mingw32"
+- "mingw-w64"
+- "g++-mingw-w64"
- "zip"
+- "unzip"
- "faketime"
+- "unzip"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
- "qt-everywhere-opensource-src-4.8.3.tar.gz"
-- "bitcoin-deps-0.0.5.zip"
+- "bitcoin-deps-win32-gitian-r9.zip"
script: |
+ #
+ HOST=i686-w64-mingw32
INSTDIR="$HOME/qt/"
+ #
mkdir $INSTDIR
+ mkdir -p $INSTDIR/host/bin
#
# Need mingw-compiled openssl from bitcoin-deps:
- unzip bitcoin-deps-0.0.5.zip
+ unzip bitcoin-deps-win32-gitian-r9.zip
DEPSDIR=`pwd`
#
tar xzf qt-everywhere-opensource-src-4.8.3.tar.gz
cd qt-everywhere-opensource-src-4.8.3
sed 's/$TODAY/2011-01-30/' -i configure
- sed 's/i686-pc-mingw32-/i586-mingw32msvc-/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
- sed --posix 's|QMAKE_CFLAGS\t\t= -pipe|QMAKE_CFLAGS\t\t= -pipe -isystem /usr/i586-mingw32msvc/include/ -frandom-seed=qtbuild|' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
+ sed "s/i686-pc-mingw32-/$HOST-/" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
+ sed --posix "s|QMAKE_CFLAGS\t\t= -pipe|QMAKE_CFLAGS\t\t= -pipe -isystem /usr/$HOST/include/ -frandom-seed=qtbuild|" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
sed 's/QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions -mthreads/QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
sed 's/QMAKE_LFLAGS_EXCEPTIONS_ON = -mthreads/QMAKE_LFLAGS_EXCEPTIONS_ON = -lmingwthrd/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
- sed --posix 's/QMAKE_MOC\t\t= i586-mingw32msvc-moc/QMAKE_MOC\t\t= moc/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
- sed --posix 's/QMAKE_RCC\t\t= i586-mingw32msvc-rcc/QMAKE_RCC\t\t= rcc/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
- sed --posix 's/QMAKE_UIC\t\t= i586-mingw32msvc-uic/QMAKE_UIC\t\t= uic/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
+ sed --posix "s/QMAKE_MOC\t\t= $HOST-moc/QMAKE_MOC\t\t= moc/" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
+ sed --posix "s/QMAKE_RCC\t\t= $HOST-rcc/QMAKE_RCC\t\t= rcc/" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
+ sed --posix "s/QMAKE_UIC\t\t= $HOST-uic/QMAKE_UIC\t\t= uic/" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
# ar adds timestamps to every object file included in the static library
# providing -D as ar argument is supposed to solve it, but doesn't work as qmake strips off the arguments and adds -M to pass a script...
# which somehow cannot be combined with other flags.
# use faketime only for ar, as it confuses make/qmake into hanging sometimes
- sed --posix "s|QMAKE_LIB\t\t= i586-mingw32msvc-ar -ru|QMAKE_LIB\t\t= $HOME/ar -Dr|" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
+ sed --posix "s|QMAKE_LIB\t\t= $HOST-ar -ru|QMAKE_LIB\t\t= $HOME/ar -Dr|" -i mkspecs/unsupported/win32-g++-cross/qmake.conf
echo '#!/bin/bash' > $HOME/ar
echo 'export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1' >> $HOME/ar
- echo 'i586-mingw32msvc-ar "$@"' >> $HOME/ar
+ echo "$HOST-ar \"\$@\"" >> $HOME/ar
chmod +x $HOME/ar
#export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
export TZ=UTC
# Compile static libraries, and use statically linked openssl (-openssl-linked):
- OPENSSL_LIBS="-L$DEPSDIR/openssl-1.0.1c -lssl -lcrypto -lgdi32" ./configure -prefix $INSTDIR -I $DEPSDIR/openssl-1.0.1c/include -confirm-license -release -opensource -static -no-qt3support -xplatform unsupported/win32-g++-cross -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -no-script -no-scripttools -no-javascript-jit -no-webkit -no-svg -no-xmlpatterns -no-sql-sqlite -no-nis -no-cups -no-iconv -no-dbus -no-gif -no-libtiff -no-opengl -nomake examples -nomake demos -nomake docs -no-feature-style-plastique -no-feature-style-cleanlooks -no-feature-style-motif -no-feature-style-cde -no-feature-style-windowsce -no-feature-style-windowsmobile -no-feature-style-s60 -openssl-linked
+ OPENSSL_LIBS="-L$DEPSDIR/lib -lssl -lcrypto -lgdi32" ./configure -prefix $INSTDIR -bindir $INSTDIR/host/bin -I $DEPSDIR/include -confirm-license -release -opensource -static -no-qt3support -xplatform unsupported/win32-g++-cross -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -no-script -no-scripttools -no-javascript-jit -no-webkit -no-svg -no-xmlpatterns -no-sql-sqlite -no-nis -no-cups -no-iconv -no-dbus -no-gif -no-libtiff -no-opengl -nomake examples -nomake demos -nomake docs -no-feature-style-plastique -no-feature-style-cleanlooks -no-feature-style-motif -no-feature-style-cde -no-feature-style-windowsce -no-feature-style-windowsmobile -no-feature-style-s60 -openssl-linked
find . -name *.prl | xargs -l sed 's|/\.||' -i
find . -name *.prl | xargs -l sed 's|/$||' -i
make $MAKEOPTS install
@@ -53,4 +60,4 @@ script: |
# as zip stores file timestamps, use faketime to intercept stat calls to set dates for all files to reference date
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
- zip -r $OUTDIR/qt-win32-4.8.3-gitian-r2.zip *
+ zip -r $OUTDIR/qt-win32-4.8.3-gitian-r4.zip *
diff --git a/contrib/gitian-downloader/linux-download-config b/contrib/gitian-downloader/linux-download-config
index 8340a5dd24..ae0377a704 100644
--- a/contrib/gitian-downloader/linux-download-config
+++ b/contrib/gitian-downloader/linux-download-config
@@ -39,4 +39,8 @@ signers:
weight: 40
name: "Warren Togami"
key: wtogami
+ 9692B91BBF0E8D34DFD33B1882C5C009628ECF0C:
+ weight: 1
+ name: michagogo
+ key: michagogo
minimum_weight: 120
diff --git a/contrib/gitian-downloader/michagogo-key.pgp b/contrib/gitian-downloader/michagogo-key.pgp
new file mode 100644
index 0000000000..47bc404554
--- /dev/null
+++ b/contrib/gitian-downloader/michagogo-key.pgp
@@ -0,0 +1,59 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.12 (GNU/Linux)
+
+mQENBFGeqJ4BCADb7SI3/+q93gIvN0AGRg9Mtz73OLIOzCHeeoyn+tp7JcYNzxkQ
+9lfeXiEfn72Sh8gHkLtLIqr7HlIMo8DxSS8JPRVjlJGkNyAW4SeEwN2wNa5OV8k0
+N4jBa9a1csFyCyrEkPKvkUpBkQDvNXjNxyEhHwyZqPanKxy6NXIHOJji8ObOMQXI
+T9HwJrpjRth3u4uKG968JBTEyAXAmkt0Zidl1Ykgzcedk4mJSE9uZCW8DjSv2wML
+XcQz8+dYsoskT3KRdkowLHxAfj1BNyNc1+rKLghliM5vSQWi+Lbhi1Bxh4sY1UwA
+lKnAGqrnAGyIvCtkwTq5QI6ufF2ZY44bvVgpABEBAAG0IU1pY2hhZ29nbyA8bWlj
+aGFnb2dvQHNlcnZlci5mYWtlPokBOAQTAQIAIgUCUZ6ongIbAwYLCQgHAwIGFQgC
+CQoLBBYCAwECHgECF4AACgkQgsXACWKOzwzMUAgAuqUmK10xE5C3lUym2f72z0t6
+a2NM5Wfjr9//Y1/okC36C5XAMEtN2UwckPzzJ5p5D5y5yzwfZq5Jd8Py29VQIMsV
+7FbC1a0H3D+bCyX+JJ6FAmUbnWOQ/+mydYc74RvD8iwjePNT6kziZNv6dMGctJTl
+0alwjtQYgyGkeYKnIxbcyjHX/IawLUrunb/6mSKun87T8+NM/omfFCTc3l8TakpM
+0wyNYRiUkIfUBvB8sDUU3A80qKN/hqRKvlFu3+/kMiAc9ZYQrbmsB+sYWdmM+4zw
+8NBw3yuYzWyPuoa4PR5ZmS9F11WLMR5vTRCdLudAqYsWu3LtV6vAIvlOUa2LMLRg
+TWljaGFnb2dvIChSZWdpc3RlcmVkIG5pY2sgbWljaGFnb2dvIG9uIGZyZWVub2Rl
+IGFzIG9mIE9jdG9iZXIgMTIsIDIwMTMpIDxtaWNoYWdvZ29Ac2VydmVyLmZha2U+
+iQE4BBMBAgAiBQJSWarzAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCC
+xcAJYo7PDA7nB/91wAiaMlU5nHLUu0anhNQbGvUdFgKK1zO90S5KzUdJcY438jcS
+UJW1az8l9U9JBRIfPRYVhz/Z1TAJ+dCzD7D8BXHFeGEr0zNOh87ly9aB5du7dpN2
+oSBD6wLcJpqxt4h+XjSS2CX98/2ZIJxXENE2KySaTXP39Xl3eNwvJTUBA4XlcMey
+J8KMp/IERli4H0O7vRyLgu3yYpUArTqAonzG1g2lfB35PQJfeInrRSniQ336otnZ
+A8qwJ63kfUtWVDRz0g1fnvtiLGPivDJaI5hyIaUeJPaXU1+sg7YNroDu60o2NGZh
+F+0IjHlvRfzzA+F9Vw38rpSqR3BmCdjf6Sv3iQEcBBABAgAGBQJSWa9/AAoJEH+r
+EUJn5PoE/hgH/1T2dAthVucA/hzY0nl4SMjbg+dzNlYBq00Qwx8DRKVjk5et8+kY
+oPI3DGILcr+ELnxNekeMv9WQBBtJanUh1K5ohZ6ohoR7lG18LXf5HCdspflB5Me6
+LMA6iMryEP6gIs9GFuoGe2YQavm58YrkqhcPu34dGN7kdurfEXLvDfVlh5ZbKCsP
+Gyd7Pbz04SpqykgK1udiTsLVjc70Xhv+jAMqeaCugDX6TLEwjVmZH/xsyKk2Uh3V
+Oib5FXADAtKH+vSqqhFpXrw7R/NaBzvCbas8l61DFHiUg1/bo8vsV8MtGcyZmzXJ
+C5Gm0njtGOil/g7JF9siUrpxs9Yyt/h+T2W0W01pY2hhZ29nbyAoVXNlciBhY2Nv
+dW50IG1pY2hhZ29nbyBvbiBHaXRodWIgYXMgb2YgT2N0b2JlciAxMiwgMjAxMykg
+PG1pY2hhZ29nb0BzZXJ2ZXIuZmFrZT6JATcEEwECACIFAlJZqxkCGwMGCwkIBwMC
+BhUIAgkKCwQWAgMBAh4BAheAAAoJEILFwAlijs8M+1AH+IU78ARblqTnJeSl0iWH
+mEsg4IBK30Q6/exDAcqOEm1Yc171uw2WnGmIvPYOQqxrRTvj3LoQ816dU6jrj6vY
+s+XX0R2hxy7ILh17D/3UKnHcddu7rmc7pNEqZeBXaMughqQaPOWkAIe52+qK5tsl
+sWllzTYE4jo29uZ3dAtDcKEJjBo/pIXnu1GOslE1+V4X1H9WDlwrS/JXHzyDQAjt
+maPR+3gNesDanhrRmrnT3ZXW2ZVd3vGBibhia8PWUhU1uwOH23ySWXncgsHH0Zad
+UMjd4w3YliZP/mLn2ghAxHB70IO7lgAgN3HYZeFoufP3pcK440A+CezfQiRcjHl/
+oIkBHAQQAQIABgUCUlmvfwAKCRB/qxFCZ+T6BOq9CACItsrUZPKGeWSTkMHknMrV
+K5vxIXJVCBb+Tppc0Q/J5p4EkW/RFhTwIP2zw8NLDKMh5oO9md4LXhvfIZkqQJFo
+6ZtLa3Vf+Kj7uyxezBo4QHA+G7tDsRGaMKVrEMiyLCwS1+hg9VaNzsf7zmQW7mYE
+vTLMHp3cVaSU7Mh2Dl8rnAaM/DpTUZQwZ+32Qrb/Z4HSa4f278iqoFpjEbBE2KCr
+vT5yEVvpCZ4lwSgA2a+uTlRTvVV6NA/kpsxU64tmhuEOjy+ToDqJ8wv4mqvWZxMv
+C6OhfVaXBy3U9gG8aQV0ffXGs+TbCtv8ApHd6E1/AVk0oyZGJaBVrEl688bBIWd/
+uQENBFGeqJ4BCADFmgR7oEGkFFB5qXnuNYFq1nUGDAh0dLNtAD3J6EMxUZEXdmp+
+DQHJw6/eDRQaG9EbjNZheycbVUoI8K2Y/Z268HQueGuIEIJv6cZYXoXdWCbDD4fn
+HMNUX2wNlpDqWxb7PNUEtfU9hI3gmHGlr5OiEh3iV06uiZg4n2rbWPbj45m5LJzv
+wpCrUA+pLcl9Xjw2cajaSTjdXHk9gvXTCo6s2ZS3/3Q4l+xuzZp1MGNzPQHASMKs
+wecSJKkYg6W8I5WsVlPd9a8oQCc/Nfz7BPw31MRVR/SF5FAMqaXx5uLwghVdHB2i
+cLURsOtJlCfP8W06gB7yS+MH45Jq/oxBRiJBABEBAAGJAR8EGAECAAkFAlGeqJ4C
+GwwACgkQgsXACWKOzwwT4wgAy6ICcnBZ9l2jSu+ldy57F6jf5kpKZgB9NV8V2mMA
+NeY1wMQ4VTVpU4t3s4E2LYtGNJNkPQVHbt1Pf4dGPasvMPaHMamgwgyqgYixqs0x
+D5PdKzVrfnjwTTr/ZAFdccSPmvy5/hbY0geQ/+mzdbL07+xaT58JIoG5nySDKhmC
+VeOvhDZtXMVAhEWBDPEgh/H9sEuBgMgZrzfE1j3q802qiXeQs6WtadWlQ1RN9Iq1
+ZzIi6u9/BifEIRI0pO/WwKOZdXLTemFUoakoe7uT3A74N96t0G9LZVihYbEoO+Pc
+5IaHPBV5VLeR3TB1LnnjHVf/Fwi8cnGy50kNWjcbMyEDag==
+=jyQ4
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/contrib/gitian-downloader/win32-download-config b/contrib/gitian-downloader/win32-download-config
index 49d52851b6..1ead2fddcb 100644
--- a/contrib/gitian-downloader/win32-download-config
+++ b/contrib/gitian-downloader/win32-download-config
@@ -39,4 +39,8 @@ signers:
weight: 40
name: "Warren Togami"
key: wtogami
+ 9692B91BBF0E8D34DFD33B1882C5C009628ECF0C:
+ weight: 1
+ name: michagogo
+ key: michagogo
minimum_weight: 120
diff --git a/contrib/homebrew/bitcoin.qt.pro.patch b/contrib/homebrew/bitcoin.qt.pro.patch
deleted file mode 100644
index 1001f29065..0000000000
--- a/contrib/homebrew/bitcoin.qt.pro.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
-index d938c07..e1dd4ec 100644
---- a/bitcoin-qt.pro
-+++ b/bitcoin-qt.pro
-@@ -353,7 +353,7 @@
- }
-
- isEmpty(BDB_LIB_PATH) {
-- macx:BDB_LIB_PATH = /opt/local/lib/db48
-+ macx:BDB_LIB_PATH = /usr/local/opt/berkeley-db4/lib
- }
-
- isEmpty(BDB_LIB_SUFFIX) {
-@@ -361,15 +361,15 @@
- }
-
- isEmpty(BDB_INCLUDE_PATH) {
-- macx:BDB_INCLUDE_PATH = /opt/local/include/db48
-+ macx:BDB_INCLUDE_PATH = /usr/local/opt/berkeley-db4/include
- }
-
- isEmpty(BOOST_LIB_PATH) {
-- macx:BOOST_LIB_PATH = /opt/local/lib
-+ macx:BOOST_LIB_PATH = /usr/local/opt/boost/lib
- }
-
- isEmpty(BOOST_INCLUDE_PATH) {
-- macx:BOOST_INCLUDE_PATH = /opt/local/include
-+ macx:BOOST_INCLUDE_PATH = /usr/local/opt/boost/include
- }
-
- win32:DEFINES += WIN32
diff --git a/contrib/homebrew/makefile.osx.patch b/contrib/homebrew/makefile.osx.patch
deleted file mode 100644
index 287db2fdf2..0000000000
--- a/contrib/homebrew/makefile.osx.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-diff --git a/src/makefile.osx b/src/makefile.osx
-index bef0ef3..07ef8d3 100644
---- a/src/makefile.osx
-+++ b/src/makefile.osx
-@@ -7,17 +7,21 @@
- # Originally by Laszlo Hanyecz (solar@heliacal.net)
-
- CXX=llvm-g++
--DEPSDIR=/opt/local
-+DEPSDIR=/usr/local
-+DB4DIR=/usr/local/opt/berkeley-db4
-+OPENSSLDIR=/usr/local/opt/openssl
-
- INCLUDEPATHS= \
- -I"$(CURDIR)" \
-- -I"$(CURDIR)"/obj \
-+ -I"$(CURDIR)/obj" \
- -I"$(DEPSDIR)/include" \
-- -I"$(DEPSDIR)/include/db48"
-+ -I"$(DB4DIR)/include" \
-+ -I"$(OPENSSLDIR)/include"
-
- LIBPATHS= \
- -L"$(DEPSDIR)/lib" \
-- -L"$(DEPSDIR)/lib/db48"
-+ -L"$(DB4DIR)/lib" \
-+ -L"$(OPENSSLDIR)/lib"
-
- USE_UPNP:=1
- USE_IPV6:=1
-@@ -31,14 +35,14 @@ ifdef STATIC
- TESTLIBS += \
- $(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
- LIBS += \
-- $(DEPSDIR)/lib/db48/libdb_cxx-4.8.a \
-+ $(DB4DIR)/lib/libdb_cxx-4.8.a \
- $(DEPSDIR)/lib/libboost_system-mt.a \
- $(DEPSDIR)/lib/libboost_filesystem-mt.a \
- $(DEPSDIR)/lib/libboost_program_options-mt.a \
- $(DEPSDIR)/lib/libboost_thread-mt.a \
- $(DEPSDIR)/lib/libboost_chrono-mt.a \
-- $(DEPSDIR)/lib/libssl.a \
-- $(DEPSDIR)/lib/libcrypto.a \
-+ $(OPENSSLDIR)/lib/libssl.a \
-+ $(OPENSSLDIR)/lib/libcrypto.a \
- -lz
- else
- TESTLIBS += \
diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md
new file mode 100644
index 0000000000..70b9f034cd
--- /dev/null
+++ b/contrib/linearize/README.md
@@ -0,0 +1,2 @@
+### Linearize ###
+Construct a linear, no-fork, best version of the blockchain. \ No newline at end of file
diff --git a/contrib/linearize/example-linearize.cfg b/contrib/linearize/example-linearize.cfg
new file mode 100644
index 0000000000..9e5aa404c2
--- /dev/null
+++ b/contrib/linearize/example-linearize.cfg
@@ -0,0 +1,12 @@
+
+# bitcoind RPC settings
+rpcuser=someuser
+rpcpass=somepassword
+host=127.0.0.1
+port=8332
+
+# bootstrap.dat settings
+netmagic=f9beb4d9
+max_height=250000
+output=bootstrap.dat
+
diff --git a/contrib/linearize/linearize.py b/contrib/linearize/linearize.py
new file mode 100644
index 0000000000..2d8509f83c
--- /dev/null
+++ b/contrib/linearize/linearize.py
@@ -0,0 +1,129 @@
+#!/usr/bin/python
+#
+# linearize.py: Construct a linear, no-fork, best version of the blockchain.
+#
+#
+# Copyright (c) 2013 The Bitcoin developers
+# Distributed under the MIT/X11 software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+
+import json
+import struct
+import re
+import base64
+import httplib
+import sys
+
+ERR_SLEEP = 15
+MAX_NONCE = 1000000L
+
+settings = {}
+
+class BitcoinRPC:
+ OBJID = 1
+
+ def __init__(self, host, port, username, password):
+ authpair = "%s:%s" % (username, password)
+ self.authhdr = "Basic %s" % (base64.b64encode(authpair))
+ self.conn = httplib.HTTPConnection(host, port, False, 30)
+ def rpc(self, method, params=None):
+ self.OBJID += 1
+ obj = { 'version' : '1.1',
+ 'method' : method,
+ 'id' : self.OBJID }
+ if params is None:
+ obj['params'] = []
+ else:
+ obj['params'] = params
+ self.conn.request('POST', '/', json.dumps(obj),
+ { 'Authorization' : self.authhdr,
+ 'Content-type' : 'application/json' })
+
+ resp = self.conn.getresponse()
+ if resp is None:
+ print "JSON-RPC: no response"
+ return None
+
+ body = resp.read()
+ resp_obj = json.loads(body)
+ if resp_obj is None:
+ print "JSON-RPC: cannot JSON-decode body"
+ return None
+ if 'error' in resp_obj and resp_obj['error'] != None:
+ return resp_obj['error']
+ if 'result' not in resp_obj:
+ print "JSON-RPC: no result in object"
+ return None
+
+ return resp_obj['result']
+ def getblock(self, hash, verbose=True):
+ return self.rpc('getblock', [hash, verbose])
+ def getblockhash(self, index):
+ return self.rpc('getblockhash', [index])
+
+def getblock(rpc, settings, n):
+ hash = rpc.getblockhash(n)
+ hexdata = rpc.getblock(hash, False)
+ data = hexdata.decode('hex')
+
+ return data
+
+def get_blocks(settings):
+ rpc = BitcoinRPC(settings['host'], settings['port'],
+ settings['rpcuser'], settings['rpcpass'])
+
+ outf = open(settings['output'], 'wb')
+
+ for height in xrange(settings['max_height']+1):
+ data = getblock(rpc, settings, height)
+
+ outhdr = settings['netmagic']
+ outhdr += struct.pack("<i", len(data))
+
+ outf.write(outhdr)
+ outf.write(data)
+
+ if (height % 1000) == 0:
+ sys.stdout.write("Wrote block " + str(height) + "\n")
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print "Usage: linearize.py CONFIG-FILE"
+ sys.exit(1)
+
+ f = open(sys.argv[1])
+ for line in f:
+ # skip comment lines
+ m = re.search('^\s*#', line)
+ if m:
+ continue
+
+ # parse key=value lines
+ m = re.search('^(\w+)\s*=\s*(\S.*)$', line)
+ if m is None:
+ continue
+ settings[m.group(1)] = m.group(2)
+ f.close()
+
+ if 'netmagic' not in settings:
+ settings['netmagic'] = 'f9beb4d9'
+ if 'output' not in settings:
+ settings['output'] = 'bootstrap.dat'
+ if 'host' not in settings:
+ settings['host'] = '127.0.0.1'
+ if 'port' not in settings:
+ settings['port'] = 8332
+ if 'max_height' not in settings:
+ settings['max_height'] = 250000
+ if 'rpcuser' not in settings or 'rpcpass' not in settings:
+ print "Missing username and/or password in cfg file"
+ sys.exit(1)
+
+ settings['netmagic'] = settings['netmagic'].decode('hex')
+ settings['port'] = int(settings['port'])
+ settings['max_height'] = int(settings['max_height'])
+
+ get_blocks(settings)
+
+
diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md
new file mode 100644
index 0000000000..5f0611f20c
--- /dev/null
+++ b/contrib/macdeploy/README.md
@@ -0,0 +1,19 @@
+### MacDeploy ###
+
+You will need the appscript package for the fancy disk image creation to work:
+
+ sudo easy_install appscript
+
+For Snow Leopard (which uses [Python 2.6](http://www.python.org/download/releases/2.6/)), you will need the param_parser package:
+
+ sudo easy_install argparse
+
+This script should not be run manually, instead, after building as usual:
+
+ make deploy
+
+During the process, the disk image window will pop up briefly where the fancy
+settings are applied. This is normal, please do not interfere.
+
+When finished, it will produce `Bitcoin-Qt.dmg`.
+
diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus
index 11140d3b85..533be6cffa 100755
--- a/contrib/macdeploy/macdeployqtplus
+++ b/contrib/macdeploy/macdeployqtplus
@@ -651,6 +651,23 @@ elif config.sign:
# ------------------------------------------------
if config.dmg is not None:
+
+ #Patch in check_output for Python 2.6
+ if "check_output" not in dir( subprocess ):
+ def f(*popenargs, **kwargs):
+ if 'stdout' in kwargs:
+ raise ValueError('stdout argument not allowed, it will be overridden.')
+ process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
+ output, unused_err = process.communicate()
+ retcode = process.poll()
+ if retcode:
+ cmd = kwargs.get("args")
+ if cmd is None:
+ cmd = popenargs[0]
+ raise CalledProcessError(retcode, cmd)
+ return output
+ subprocess.check_output = f
+
def runHDIUtil(verb, image_basename, **kwargs):
hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"]
if kwargs.has_key("capture_stdout"):
diff --git a/contrib/macdeploy/notes.txt b/contrib/macdeploy/notes.txt
deleted file mode 100644
index 3d74901437..0000000000
--- a/contrib/macdeploy/notes.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-macdeployqtplus works best on OS X Lion, for Snow Leopard you'd need to install
-Python 2.7 and make it your default Python installation.
-
-You will need the appscript package for the fancy disk image creation to work.
-Install it by invoking "sudo easy_install appscript".
-
-This script should be invoked in the target directory like this:
-$source_dir/contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist -verbose 2
-
-During the process, the disk image window will pop up briefly where the fancy
-settings are applied. This is normal, please do not interfere.
-
-You can also set up Qt Creator for invoking the script. For this, go to the
-"Projects" tab on the left side, switch to "Run Settings" above and add a
-deploy configuration. Next add a deploy step choosing "Custom Process Step".
-Fill in the following.
-
-Enable custom process step: [x]
-Command: %{sourceDir}/contrib/macdeploy/macdeployqtplus
-Working directory: %{buildDir}
-Command arguments: Bitcoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist -verbose 2
-
-After that you can start the deployment process through the menu with
-Build -> Deploy Project "bitcoin-qt"
-
diff --git a/contrib/pyminer/README b/contrib/pyminer/README.md
index d1596575dd..119d51bdc7 100644
--- a/contrib/pyminer/README
+++ b/contrib/pyminer/README.md
@@ -1,5 +1,6 @@
+### PyMiner ###
-This is a 'getwork' CPU mining client for bitcoin.
+This is a 'getwork' CPU mining client for Bitcoin.
It is pure-python, and therefore very, very slow. The purpose is to
provide a reference implementation of a miner, for study.
diff --git a/contrib/qos/README b/contrib/qos/README.md
index f419685744..5e0a975fc6 100644
--- a/contrib/qos/README
+++ b/contrib/qos/README.md
@@ -1,3 +1,5 @@
+### Qos ###
+
This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Bitcoin network. It limits outbound TCP traffic with a source or destination port of 8333, but not if the destination IP is within a LAN (defined as 192.168.x.x).
This means one can have an always-on bitcoind instance running, and another local bitcoind/bitcoin-qt instance which connects to this node and receives blocks from it.
diff --git a/contrib/seeds/README b/contrib/seeds/README.md
index 97e3e1ec71..f9a0c277e2 100644
--- a/contrib/seeds/README
+++ b/contrib/seeds/README.md
@@ -1,9 +1,11 @@
+### Seeds ###
+
Utility to generate the pnSeed[] array that is compiled into the client
-(see src/net.cpp).
+(see [src/net.cpp](/src/net.cpp)).
The 600 seeds compiled into the 0.8 release were created from sipa's DNS seed data, like this:
-curl -s http://bitcoin.sipa.be/seeds.txt | head -1000 | makeseeds.py
+ curl -s http://bitcoin.sipa.be/seeds.txt | head -1000 | makeseeds.py
The input to makeseeds.py is assumed to be approximately sorted from most-reliable to least-reliable,
with IP:port first on each line (lines that don't match IPv4:port are ignored).
diff --git a/contrib/spendfrom/README b/contrib/spendfrom/README.md
index 8a087a0c1e..bc4def5f74 100644
--- a/contrib/spendfrom/README
+++ b/contrib/spendfrom/README.md
@@ -1,16 +1,18 @@
+### SpendFrom ###
+
Use the raw transactions API to send coins received on a particular
address (or addresses).
-Depends on jsonrpc
+Depends on `jsonrpc`
Usage:
-spendfrom.py --from=FROMADDRESS1[,FROMADDRESS2] --to=TOADDRESS --amount=amount \
- --fee=fee --datadir=/path/to/.bitcoin --testnet --dry_run
+ spendfrom.py --from=FROMADDRESS1[,FROMADDRESS2] --to=TOADDRESS --amount=amount \
+ --fee=fee --datadir=/path/to/.bitcoin --testnet --dry_run
With no arguments, outputs a list of amounts associated with addresses.
-With arguments, sends coins received by the FROMADDRESS addresses to the TOADDRESS.
+With arguments, sends coins received by the `FROMADDRESS` addresses to the `TOADDRESS`.
You may explictly specify how much fee to pay (a fee more than 1% of the amount
will fail, though, to prevent bitcoin-losing accidents). Spendfrom may fail if
@@ -18,11 +20,11 @@ it thinks the transaction would never be confirmed (if the amount being sent is
too small, or if the transaction is too many bytes for the fee).
If a change output needs to be created, the change will be sent to the last
-FROMADDRESS (if you specify just one FROMADDRESS, change will go back to it).
+`FROMADDRESS` (if you specify just one `FROMADDRESS`, change will go back to it).
-If --datadir is not specified, the default datadir is used.
+If `--datadir` is not specified, the default datadir is used.
-The --dry_run option will just create and sign the the transaction and print
+The `--dry_run` option will just create and sign the the transaction and print
the transaction data (as hexadecimal), instead of broadcasting it.
If the transaction is created and broadcast successfully, a transaction id
diff --git a/contrib/test-patches/README b/contrib/test-patches/README.md
index ed754cea7a..def40b0d6c 100644
--- a/contrib/test-patches/README
+++ b/contrib/test-patches/README.md
@@ -1,4 +1,7 @@
+### Test Patches ###
+
These patches are applied when the automated pull-tester
tests each pull and when master is tested using jenkins.
You can find more information about the tests run at
-http://jenkins.bluematt.me/pull-tester/files/
+[http://jenkins.bluematt.me/pull-tester/files/
+](http://jenkins.bluematt.me/pull-tester/files/) \ No newline at end of file
diff --git a/contrib/testgen/README b/contrib/testgen/README
deleted file mode 100644
index 02d6c4cdc2..0000000000
--- a/contrib/testgen/README
+++ /dev/null
@@ -1 +0,0 @@
-Utilities to generate test vectors for the data-driven Bitcoin tests
diff --git a/contrib/testgen/README.md b/contrib/testgen/README.md
new file mode 100644
index 0000000000..83624f443a
--- /dev/null
+++ b/contrib/testgen/README.md
@@ -0,0 +1,8 @@
+### TestGen ###
+
+Utilities to generate test vectors for the data-driven Bitcoin tests.
+
+Usage:
+
+ gen_base58_test_vectors.py valid 50 > ../../src/test/data/base58_keys_valid.json
+ gen_base58_test_vectors.py invalid 50 > ../../src/test/data/base58_keys_invalid.json \ No newline at end of file
diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifysfbinaries/README.md
new file mode 100644
index 0000000000..caa4073605
--- /dev/null
+++ b/contrib/verifysfbinaries/README.md
@@ -0,0 +1,7 @@
+### Verify SF Binaries ###
+This script attempts to download the signature file `SHA256SUMS.asc` from SourceForge.
+
+It first checks if the signature passes, and then downloads the files specified in
+the file, and checks if the hashes of these files match those that are specified
+in the signature file. The script returns 0 if everything passes the checks. It returns 1 if either the
+signature check or the hash check doesn't pass. If an error occurs the return value is 2 \ No newline at end of file
diff --git a/contrib/wallettools/README.md b/contrib/wallettools/README.md
new file mode 100644
index 0000000000..358f52569e
--- /dev/null
+++ b/contrib/wallettools/README.md
@@ -0,0 +1,2 @@
+### Wallet Tools ###
+Contains a wallet change password and unlock script.
diff --git a/doc/README.md b/doc/README.md
index 1238033fb7..068ed988d1 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -3,22 +3,15 @@ Bitcoin 0.8.2 BETA
Copyright (c) 2009-2013 Bitcoin Developers
+License
+---------------------
Distributed under the [MIT/X11 software license](http://www.opensource.org/licenses/mit-license.php).
This product includes software developed by the OpenSSL Project for use in the [OpenSSL Toolkit](http://www.openssl.org/). This product includes
cryptographic software written by Eric Young ([eay@cryptsoft.com](mailto:eay@cryptsoft.com)), and UPnP software written by Thomas Bernard.
-
-Intro
----------------------
-Bitcoin is a free open source peer-to-peer electronic cash system that is
-completely decentralized, without the need for a central server or trusted
-parties. Users hold the crypto keys to their own money and transact directly
-with each other, with the help of a P2P network to check for double-spending.
-
-
Setup
---------------------
-[Bitcoin-Qt](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions; depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more.
+[Bitcoin-Qt](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more.
### Unix
@@ -44,17 +37,20 @@ Unpack the files into a directory and run bitcoin-qt.exe.
* See the documentation at the [Bitcoin Wiki](https://en.bitcoin.it/wiki/Main_Page)
for help and more information.
* Ask for help on [#bitcoin](http://webchat.freenode.net?channels=bitcoin) on Freenode. If you don't have an IRC client use [webchat here](http://webchat.freenode.net?channels=bitcoin).
-* Ask for help on the [BitcoinTalk](https://bitcointalk.org/) forums.
+* Ask for help on the [BitcoinTalk](https://bitcointalk.org/) forums, in the [technical support board](https://bitcointalk.org/index.php?board=4.0).
Building
---------------------
-- [Bitcoin-Qt Readme](readme-qt.md)
+The following are developer notes on how to build Bitcoin on your native platform. They are not complete guide, but include notes on the necessary libraries, compile flags, etc.
+
- [OSX Build Notes](build-osx.md)
- [Unix Build Notes](build-unix.md)
- [Windows Build Notes](build-msw.md)
Development
---------------------
+The Bitcoin repo's [root README](https://github.com/bitcoin/bitcoin/blob/master/README.md) contains relevant information on the development process and automated testing.
+
- [Coding Guidelines](coding.md)
- [Multiwallet Qt Development](multiwallet-qt.md)
- [Release Notes](release-notes.md)
@@ -67,4 +63,4 @@ Other Pages
---------------------
- [Assets Attribution](assets-attribution.md)
- [Files](files.md)
-- [Tor Support](tor.md) \ No newline at end of file
+- [Tor Support](tor.md)
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 4653bba495..422b46cc3a 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -5,10 +5,12 @@ Some notes on how to build Bitcoin in Unix.
To Build
---------------------
- cd src/
- make -f makefile.unix # Headless bitcoin
+ ./autogen.sh
+ ./configure
+ make
-See [readme-qt.md](readme-qt.md) for instructions on building Bitcoin-Qt, the graphical user interface.
+This will build bitcoin-qt as well if the dependencies are met.
+See [readme-qt.md](readme-qt.md) for more information.
Dependencies
---------------------
@@ -19,18 +21,21 @@ Dependencies
libdb4.8 Berkeley DB Blockchain & wallet storage
libboost Boost C++ Library
miniupnpc UPnP Support Optional firewall-jumping support
+ qt GUI GUI toolkit
+ protobuf Payments in GUI Data interchange format used for payment protocol
+ libqrencode QR codes in GUI Optional for generating QR codes
[miniupnpc](http://miniupnp.free.fr/) may be used for UPnP port mapping. It can be downloaded from [here](
http://miniupnp.tuxfamily.org/files/). UPnP support is compiled in and
-turned off by default. Set USE_UPNP to a different value to control this:
+turned off by default. See the configure options for upnp behavior desired:
- USE_UPNP= No UPnP support miniupnp not required
- USE_UPNP=0 (the default) UPnP support turned off by default at runtime
- USE_UPNP=1 UPnP support turned on by default at runtime
+ --with-miniupnpc No UPnP support miniupnp not required
+ --disable-upnp-default (the default) UPnP support turned off by default at runtime
+ --enable-upnp-default UPnP support turned on by default at runtime
IPv6 support may be disabled by setting:
- USE_IPV6=0 Disable IPv6 support
+ --disable-ipv6 Disable IPv6 support
Licenses of statically linked libraries:
Berkeley DB New BSD license with additional requirement that linked
@@ -44,21 +49,25 @@ Licenses of statically linked libraries:
- Berkeley DB 4.8.30.NC
- Boost 1.37
- miniupnpc 1.6
+- qt 4.8.3
+- protobuf 2.5.0
+- libqrencode 3.2.0
Dependency Build Instructions: Ubuntu & Debian
----------------------------------------------
Build requirements:
sudo apt-get install build-essential
+ sudo apt-get install libtool autotools-dev
sudo apt-get install libssl-dev
-for Ubuntu 12.04:
+for Ubuntu 12.04 and later:
sudo apt-get install libboost-all-dev
db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
- Ubuntu precise has packages for libdb5.1-dev and libdb5.1++-dev,
+ Ubuntu 12.04 and later have packages for libdb5.1-dev and libdb5.1++-dev,
but using these will break binary wallet compatibility, and is not recommended.
for other Ubuntu & Debian:
@@ -70,23 +79,24 @@ for other Ubuntu & Debian:
Optional:
- sudo apt-get install libminiupnpc-dev (see USE_UPNP compile flag)
+ sudo apt-get install libminiupnpc-dev (see --with-miniupnpc and --enable-upnp-default)
+Dependencies for the GUI: Ubuntu & Debian
+-----------------------------------------
-Dependency Build Instructions: Gentoo
--------------------------------------
+If you want to build Bitcoin-Qt, make sure that the required packages for Qt development
+are installed. Qt 4 is currently necessary to build the GUI.
-Note: If you just want to install bitcoind on Gentoo, you can add the Bitcoin overlay and use your package manager:
+To build with Qt 4 you need the following:
- layman -a bitcoin && emerge bitcoind
- emerge -av1 --noreplace boost glib openssl sys-libs/db:4.8
+ apt-get install libqt4-dev libprotobuf-dev
-Take the following steps to build (no UPnP support):
+libqrencode (optional) can be installed with:
- cd ${BITCOIN_DIR}/src
- make -f makefile.unix USE_UPNP= USE_IPV6=1 BDB_INCLUDE_PATH='/usr/include/db4.8'
- strip bitcoind
+ apt-get install libqrencode-dev
+Once these are installed, they will be found by configure and a bitcoin-qt executable will be
+built by default.
Notes
-----
@@ -123,7 +133,13 @@ If you need to build Boost yourself:
Security
--------
To help make your bitcoin installation more secure by making certain attacks impossible to
-exploit even if a vulnerability is found, you can take the following measures:
+exploit even if a vulnerability is found, binaries are hardened by default.
+This can be disabled with:
+
+./configure --enable-hardening
+
+
+Hardening enables the following features:
* Position Independent Executable
Build position independent code to take advantage of Address Space Layout Randomization
@@ -135,10 +151,6 @@ exploit even if a vulnerability is found, you can take the following measures:
On an Amd64 processor where a library was not compiled with -fPIC, this will cause an error
such as: "relocation R_X86_64_32 against `......' can not be used when making a shared object;"
- To build with PIE, use:
-
- make -f makefile.unix ... -e PIE=1
-
To test that you have built PIE executable, install scanelf, part of paxutils, and use:
scanelf -e ./bitcoin
diff --git a/doc/readme-qt.md b/doc/readme-qt.md
deleted file mode 100644
index cbaaf645af..0000000000
--- a/doc/readme-qt.md
+++ /dev/null
@@ -1,128 +0,0 @@
-Bitcoin-Qt Readme
-===============================
-Contains build and configuration instructions for Bitcoin-Qt (Qt4 GUI for Bitcoin).
-
-Build Instructions
----------------------
-
-### Debian
-
-
-First, make sure that the required packages for Qt4 development of your
-distribution are installed, these are
-
-
-
-for Debian and Ubuntu <= 11.10 :
-
-
- apt-get install qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
- libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
- libssl-dev libdb4.8++-dev libprotobuf-dev protobuf-compiler
-
-for Ubuntu >= 12.04 (please read the 'Berkely DB version warning' below):
-
- apt-get install qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
- libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
- libssl-dev libdb++-dev libminiupnpc-dev libprotobuf-dev protobuf-compiler
-
-For Qt 5 you need the following, otherwise you get an error with lrelease when running qmake:
-
-
- apt-get install qt5-qmake libqt5gui5 libqt5core5 libqt5dbus5 qttools5-dev-tools
-
-then execute the following:
-
- qmake
- make
-
-Alternatively, install [Qt Creator](http://qt-project.org/downloads/) and open the `bitcoin-qt.pro` file.
-An executable named `bitcoin-qt` will be built.
-
-
-
-### Mac OS X
-
-* Download and install the [Qt Mac OS X SDK](https://qt-project.org/downloads). It is recommended to also install Apple's Xcode with UNIX tools.
-* Download and install either [MacPorts](https://www.macports.org/) or [HomeBrew](http://mxcl.github.io/homebrew/).
-* Execute the following commands in a terminal to get the dependencies using MacPorts
-
- sudo port selfupdate
- sudo port install boost db48 miniupnpc protobuf-cpp
-
-* Execute the following commands in a terminal to get the dependencies using HomeBrew:
-
- brew update
- brew install boost miniupnpc openssl berkeley-db4 protobuf
-
-- If using HomeBrew, edit `bitcoin-qt.pro` to account for library location differences. There's a diff in `contrib/homebrew/bitcoin-qt-pro.patch` that shows what you need to change, or you can just patch by doing
-
- patch -p1 < contrib/homebrew/bitcoin.qt.pro.patch
-
-- Open the bitcoin-qt.pro file in Qt Creator and build as normal (cmd+B)
-
-
-Build Configuration Options
----------------------
-
-### UPnP port forwarding
-
-To use UPnP for port forwarding behind a NAT router (recommended, as more connections overall allow for a faster and more stable bitcoin experience), pass the following argument to qmake:
-
-
-
- qmake "USE_UPNP=1"
-
-(in **Qt Creator**, you can find the setting for additional qmake arguments under "Projects" -> "Build Settings" -> "Build Steps", then click "Details" next to **qmake**)
-
-This requires miniupnpc for UPnP port mapping. It can be downloaded from [here](
-http://miniupnp.tuxfamily.org/files/). UPnP support is not compiled in by default.
-
-Set USE_UPNP to a different value to control this:
-
-
- USE_UPNP=- no UPnP support, miniupnpc not required;
- USE_UPNP=0 (the default) built with UPnP, support turned off by default at runtime;
- USE_UPNP=1 build with UPnP support turned on by default at runtime.
-
-### Notification support for recent (k)ubuntu versions
-
-To see desktop notifications on (k)ubuntu versions starting from 10.04, enable usage of the
-FreeDesktop notification interface through DBUS using the following qmake option:
-
-
-
- qmake "USE_DBUS=1"
-
-### Generation of QR codes
-
-[libqrencode](http://fukuchi.org/works/qrencode/) may be used to generate QRCode images for payment requests. Pass the USE_QRCODE flag to qmake to control this:
-
-
- USE_QRCODE=0 (the default) No QRCode support - libarcode not required
- USE_QRCODE=1 QRCode support enabled
-
-Warnings
----------------------
-
-### Berkely DB Version Warning
-
-
-A warning for people using the *static binary* version of Bitcoin on a Linux/UNIX-ish system (tl;dr: **Berkely DB databases are not forward compatible**).
-
-The static binary version of Bitcoin is linked against libdb4.8 (see also [this Debian issue](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=621425)).
-
-Now the nasty thing is that databases from 5.X are not compatible with 4.X.
-
-If the globally installed development package of Berkely DB installed on your system is 5.X, any source you build yourself will be linked against that. The first time you run with a 5.X version the database will be upgraded, and 4.X cannot open the new format. This means that you cannot go back to the old statically linked version without significant hassle!
-
-### Ubuntu 11.10 Warning
-
-
-Ubuntu 11.10 has a package called 'qt-at-spi' installed by default. At the time of writing, having that package installed causes bitcoin-qt to crash intermittently. The issue has been reported as [launchpad bug 857790](https://bugs.launchpad.net/ubuntu/+source/qt-at-spi/+bug/857790), but
-isn't yet fixed.
-
-Until the bug is fixed, you can remove the qt-at-spi package to work around the problem, though this will presumably disable screen reader functionality for Qt apps:
-
- sudo apt-get remove qt-at-spi
-
diff --git a/doc/release-process.md b/doc/release-process.md
index 7b0a73a81e..9e0b860a8c 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -31,26 +31,34 @@ Release Process
export SIGNER=(your gitian key, ie bluematt, sipa, etc)
export VERSION=(new version, e.g. 0.8.0)
+ pushd ./bitcoin
+ git checkout v${VERSION}
+ popd
pushd ./gitian-builder
Fetch and build inputs: (first time, or when dependency versions change)
mkdir -p inputs; cd inputs/
wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.6.tar.gz' -O miniupnpc-1.6.tar.gz
- wget 'http://www.openssl.org/source/openssl-1.0.1c.tar.gz'
+ wget 'https://www.openssl.org/source/openssl-1.0.1c.tar.gz'
wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
- wget 'http://zlib.net/zlib-1.2.6.tar.gz'
- wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.9.tar.gz'
- wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2'
- wget 'http://downloads.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2'
- wget 'http://releases.qt-project.org/qt4/source/qt-everywhere-opensource-src-4.8.3.tar.gz'
+ wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/history/zlib/zlib-1.2.6.tar.gz'
+ wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/history/libpng15/libpng-1.5.9.tar.gz'
+ wget 'https://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2'
+ wget 'https://downloads.sourceforge.net/project/boost/boost/1.54.0/boost_1_54_0.tar.bz2'
+ wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O \
+ boost-mingw-gas-cross-compile-2013-03-03.patch
+ wget 'https://download.qt-project.org/archive/qt/4.8/4.8.3/qt-everywhere-opensource-src-4.8.3.tar.gz'
+ wget 'https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2'
cd ..
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-win32.yml
- mv build/out/boost-win32-1.50.0-gitian2.zip inputs/
- ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml
- mv build/out/qt-win32-4.8.3-gitian-r1.zip inputs/
+ mv build/out/boost-win32-*.zip inputs/
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/deps-win32.yml
- mv build/out/bitcoin-deps-0.0.5.zip inputs/
+ mv build/out/bitcoin-deps-*.zip inputs/
+ ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml
+ mv build/out/qt-win32-*.zip inputs/
+ ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/protobuf-win32.yml
+ mv build/out/protobuf-win32-*.zip inputs/
Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32:
diff --git a/doc/tor.md b/doc/tor.md
index 86d56cffd5..6057801d34 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -48,6 +48,7 @@ config file):
HiddenServiceDir /var/lib/tor/bitcoin-service/
HiddenServicePort 8333 127.0.0.1:8333
+ HiddenServicePort 18333 127.0.0.1:18333
The directory can be different of course, but (both) port numbers should be equal to
your bitcoind's P2P listen port (8333 by default).
diff --git a/doc/translation_process.md b/doc/translation_process.md
index 1724e95378..006726b953 100644
--- a/doc/translation_process.md
+++ b/doc/translation_process.md
@@ -32,14 +32,13 @@ This directory contains all translations. Filenames must adhere to this format:
`src/qt/locale/bitcoin_en.ts` is treated in a special way. It is used as the
source for all other translations. Whenever a string in the code is changed
-this file must be updated to reflect those changes. This can be accomplished
-by running `lupdate` (included in the Qt SDK). Also, a custom script is used
+this file must be updated to reflect those changes. A custom script is used
to extract strings from the non-Qt parts. This script makes use of `gettext`,
so make sure that utility is installed (ie, `apt-get install gettext` on
-Ubuntu/Debian):
-
- python share/qt/extract_strings_qt.py
- lupdate bitcoin-qt.pro -no-obsolete -locations relative -ts src/qt/locale/bitcoin_en.ts
+Ubuntu/Debian). Once this has been updated, lupdate (included in the Qt SDK)
+is used to update bitcoin_en.ts. This process has been automated, from src/qt,
+simply run:
+ make translate
##### Handling of plurals in the source file
diff --git a/doc/unit-tests.md b/doc/unit-tests.md
index d6fb2d8e2d..2c991eb03a 100644
--- a/doc/unit-tests.md
+++ b/doc/unit-tests.md
@@ -1,35 +1,18 @@
-Compiling/running bitcoind unit tests
+Compiling/running unit tests
------------------------------------
-bitcoind unit tests are in the `src/test/` directory; they
-use the Boost::Test unit-testing framework.
+Unit tests will be automatically compiled if dependencies were met in configure
+and tests weren't explicitly disabled.
-To compile and run the tests:
+After configuring, they can be run with 'make check'.
- cd src
- make -f makefile.unix test_bitcoin # Replace makefile.unix if you're not on unix
- ./test_bitcoin # Runs the unit tests
+To run the bitcoind tests manually, launch src/test/test_bitcoin .
-If all tests succeed the last line of output will be:
-`*** No errors detected`
-
-To add more tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
+To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
.cpp files in the test/ directory or add new .cpp files that
-implement new BOOST_AUTO_TEST_SUITE sections (the makefiles are
-set up to add test/*.cpp to test_bitcoin automatically).
-
-
-Compiling/running Bitcoin-Qt unit tests
----------------------------------------
-
-Bitcoin-Qt unit tests are in the src/qt/test/ directory; they
-use the Qt unit-testing framework.
-
-To compile and run the tests:
+implement new BOOST_AUTO_TEST_SUITE sections.
- qmake bitcoin-qt.pro BITCOIN_QT_TEST=1
- make
- ./bitcoin-qt_test
+To run the bitcoin-qt tests manualy, launch src/qt/test/bitcoin-qt_test
-To add more tests, add them to the `src/qt/test/` directory,
-the `src/qt/test/test_main.cpp` file, and bitcoin-qt.pro.
+To add more bitcoin-qt tests, add them to the `src/qt/test/` directory and
+the `src/qt/test/test_main.cpp` file.
diff --git a/pkg.m4 b/pkg.m4
new file mode 100644
index 0000000000..c5b26b52e6
--- /dev/null
+++ b/pkg.m4
@@ -0,0 +1,214 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+
+# PKG_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable pkgconfigdir as the location where a module
+# should install pkg-config .pc files. By default the directory is
+# $libdir/pkgconfig, but the default can be changed by passing
+# DIRECTORY. The user can override through the --with-pkgconfigdir
+# parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_INSTALLDIR
+
+
+# PKG_NOARCH_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable noarch_pkgconfigdir as the location where a
+# module should install arch-independent pkg-config .pc files. By
+# default the directory is $datadir/pkgconfig, but the default can be
+# changed by passing DIRECTORY. The user can override through the
+# --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_NOARCH_INSTALLDIR
+
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
diff --git a/qa/pull-tester/build-tests.sh.in b/qa/pull-tester/build-tests.sh.in
new file mode 100755
index 0000000000..461e7be048
--- /dev/null
+++ b/qa/pull-tester/build-tests.sh.in
@@ -0,0 +1,74 @@
+#!/bin/bash
+# Param1: The prefix to mingw staging
+# Param2: Path to java comparison tool
+# Param3: Number of make jobs. Defaults to 1.
+
+# Exit immediately if anything fails:
+set -e
+set -o xtrace
+
+MINGWPREFIX=$1
+JAVA_COMPARISON_TOOL=$2
+JOBS=${3-1}
+OUT_DIR=${4-}
+
+if [ $# -lt 2 ]; then
+ echo "Usage: $0 [mingw-prefix] [java-comparison-tool] <make jobs> <save output dir>"
+ exit 1
+fi
+
+DISTDIR=@PACKAGE@-@VERSION@
+
+# Cross-compile for windows first (breaking the mingw/windows build is most common)
+cd @abs_top_srcdir@
+make distdir
+mv $DISTDIR win32-build
+cd win32-build
+./configure --disable-silent-rules --disable-ccache --prefix=$MINGWPREFIX --host=i586-mingw32msvc --with-qt-bindir=$MINGWPREFIX/host/bin --with-qt-plugindir=$MINGWPREFIX/plugins --with-qt-incdir=$MINGWPREFIX/include --with-boost=$MINGWPREFIX --with-protoc-bindir=$MINGWPREFIX/host/bin CPPFLAGS=-I$MINGWPREFIX/include LDFLAGS=-L$MINGWPREFIX/lib
+make -j$JOBS
+
+# And compile for Linux:
+cd @abs_top_srcdir@
+make distdir
+mv $DISTDIR linux-build
+cd linux-build
+# TODO: re-enable blockchain tester tool, as of 11 Oct 2013 is it not working properly
+# on the pull-tester machine.
+#./configure --disable-silent-rules --disable-ccache --with-comparison-tool="$JAVA_COMPARISON_TOOL"
+./configure --disable-silent-rules --disable-ccache
+make -j$JOBS
+
+# link interesting binaries to parent out/ directory, if it exists. Do this before
+# running unit tests (we want bad binaries to be easy to find)
+if [ -d "$OUT_DIR" -a -w "$OUT_DIR" ]; then
+ set +e
+ # Windows:
+ cp @abs_top_srcdir@/win32-build/src/bitcoind.exe $OUT_DIR/bitcoind.exe
+ cp @abs_top_srcdir@/win32-build/src/test/test_bitcoin.exe $OUT_DIR/test_bitcoin.exe
+ cp @abs_top_srcdir@/win32-build/src/qt/bitcoind-qt.exe $OUT_DIR/bitcoin-qt.exe
+ # Linux:
+ cp @abs_top_srcdir@/linux-build/src/bitcoind $OUT_DIR/bitcoind
+ cp @abs_top_srcdir@/linux-build/src/test/test_bitcoin $OUT_DIR/test_bitcoin
+ cp @abs_top_srcdir@/linux-build/src/qt/bitcoind-qt $OUT_DIR/bitcoin-qt
+ set -e
+fi
+
+# Run unit tests and blockchain-tester on Linux:
+cd @abs_top_srcdir@/linux-build
+make check
+
+# Clean up builds (pull-tester machine doesn't have infinite disk space)
+cd @abs_top_srcdir@/linux-build
+make clean
+cd @abs_top_srcdir@/win32-build
+make clean
+
+# TODO: Fix code coverage builds on pull-tester machine
+# # Test code coverage
+# cd @abs_top_srcdir@
+# make distdir
+# mv $DISTDIR linux-coverage-build
+# cd linux-coverage-build
+# ./configure --enable-lcov --disable-silent-rules --disable-ccache --with-comparison-tool="$JAVA_COMPARISON_TOOL"
+# make -j$JOBS
+# make cov
diff --git a/qa/pull-tester/pull-tester.py b/qa/pull-tester/pull-tester.py
new file mode 100755
index 0000000000..34dd74c7e0
--- /dev/null
+++ b/qa/pull-tester/pull-tester.py
@@ -0,0 +1,184 @@
+#!/usr/bin/python
+import json
+from urllib import urlopen
+import requests
+import getpass
+from string import Template
+import sys
+import os
+import subprocess
+
+class RunError(Exception):
+ def __init__(self, value):
+ self.value = value
+ def __str__(self):
+ return repr(self.value)
+
+def run(command, **kwargs):
+ fail_hard = kwargs.pop("fail_hard", True)
+ # output to /dev/null by default:
+ kwargs.setdefault("stdout", open('/dev/null', 'w'))
+ kwargs.setdefault("stderr", open('/dev/null', 'w'))
+ command = Template(command).substitute(os.environ)
+ if "TRACE" in os.environ:
+ if 'cwd' in kwargs:
+ print("[cwd=%s] %s"%(kwargs['cwd'], command))
+ else: print(command)
+ try:
+ process = subprocess.Popen(command.split(' '), **kwargs)
+ process.wait()
+ except KeyboardInterrupt:
+ process.terminate()
+ raise
+ if process.returncode != 0 and fail_hard:
+ raise RunError("Failed: "+command)
+ return process.returncode
+
+def checkout_pull(clone_url, commit, out):
+ # Init
+ build_dir=os.environ["BUILD_DIR"]
+ run("umount ${CHROOT_COPY}/proc", fail_hard=False)
+ run("rsync --delete -apv ${CHROOT_MASTER}/ ${CHROOT_COPY}")
+ run("rm -rf ${CHROOT_COPY}${SCRIPTS_DIR}")
+ run("cp -a ${SCRIPTS_DIR} ${CHROOT_COPY}${SCRIPTS_DIR}")
+ # Merge onto upstream/master
+ run("rm -rf ${BUILD_DIR}")
+ run("mkdir -p ${BUILD_DIR}")
+ run("git clone ${CLONE_URL} ${BUILD_DIR}")
+ run("git remote add pull "+clone_url, cwd=build_dir, stdout=out, stderr=out)
+ run("git fetch pull", cwd=build_dir, stdout=out, stderr=out)
+ if run("git merge "+ commit, fail_hard=False, cwd=build_dir, stdout=out, stderr=out) != 0:
+ return False
+ run("chown -R ${BUILD_USER}:${BUILD_GROUP} ${BUILD_DIR}", stdout=out, stderr=out)
+ run("mount --bind /proc ${CHROOT_COPY}/proc")
+ return True
+
+def commentOn(commentUrl, success, inMerge, needTests, linkUrl):
+ common_message = """
+This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/
+Contact BlueMatt on freenode if something looks broken."""
+
+ # Remove old BitcoinPullTester comments (I'm being lazy and not paginating here)
+ recentcomments = requests.get(commentUrl+"?sort=created&direction=desc",
+ auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])).json
+ for comment in recentcomments:
+ if comment["user"]["login"] == os.environ["GITHUB_USER"] and common_message in comment["body"]:
+ requests.delete(comment["url"],
+ auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"]))
+
+ if success == True:
+ post_data = { "body" : "Automatic sanity-testing: PASSED, see " + linkUrl + " for binaries and test log." + common_message}
+ elif inMerge:
+ post_data = { "body" : "Automatic sanity-testing: FAILED MERGE, see " + linkUrl + " for test log." + """
+
+This pull does not merge cleanly onto current master""" + common_message}
+ else:
+ post_data = { "body" : "Automatic sanity-testing: FAILED BUILD/TEST, see " + linkUrl + " for binaries and test log." + """
+
+This could happen for one of several reasons:
+1. It chanages paths in makefile.linux-mingw or otherwise changes build scripts in a way that made them incompatible with the automated testing scripts (please tweak those patches in qa/pull-tester)
+2. It adds/modifies tests which test network rules (thanks for doing that), which conflicts with a patch applied at test time
+3. It does not build on either Linux i386 or Win32 (via MinGW cross compile)
+4. The test suite fails on either Linux i386 or Win32
+5. The block test-cases failed (lookup the first bNN identifier which failed in https://github.com/TheBlueMatt/test-scripts/blob/master/FullBlockTestGenerator.java)
+
+If you believe this to be in error, please ping BlueMatt on freenode or TheBlueMatt here.
+""" + common_message}
+
+ resp = requests.post(commentUrl, json.dumps(post_data), auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"]))
+
+def testpull(number, comment_url, clone_url, commit):
+ print("Testing pull %d: %s : %s"%(number, clone_url,commit))
+
+ dir = os.environ["RESULTS_DIR"] + "/" + commit + "/"
+ print(" ouput to %s"%dir)
+ if os.path.exists(dir):
+ os.system("rm -r " + dir)
+ os.makedirs(dir)
+ currentdir = os.environ["RESULTS_DIR"] + "/current"
+ os.system("rm -r "+currentdir)
+ os.system("ln -s " + dir + " " + currentdir)
+ out = open(dir + "test.log", 'w+')
+
+ resultsurl = os.environ["RESULTS_URL"] + commit
+ checkedout = checkout_pull(clone_url, commit, out)
+ if checkedout != True:
+ print("Failed to test pull - sending comment to: " + comment_url)
+ commentOn(comment_url, False, True, False, resultsurl)
+ open(os.environ["TESTED_DB"], "a").write(commit + "\n")
+ return
+
+ run("rm -rf ${CHROOT_COPY}/${OUT_DIR}", fail_hard=False);
+ run("mkdir -p ${CHROOT_COPY}/${OUT_DIR}", fail_hard=False);
+ run("chown -R ${BUILD_USER}:${BUILD_GROUP} ${CHROOT_COPY}/${OUT_DIR}", fail_hard=False)
+
+ script = os.environ["BUILD_PATH"]+"/qa/pull-tester/pull-tester.sh"
+ script += " ${BUILD_PATH} ${MINGW_DEPS_DIR} ${SCRIPTS_DIR}/BitcoindComparisonTool.jar 6 ${OUT_DIR}"
+ returncode = run("chroot ${CHROOT_COPY} sudo -u ${BUILD_USER} -H timeout ${TEST_TIMEOUT} "+script,
+ fail_hard=False, stdout=out, stderr=out)
+
+ run("mv ${CHROOT_COPY}/${OUT_DIR} " + dir)
+ run("mv ${BUILD_DIR} " + dir)
+
+ if returncode == 42:
+ print("Successfully tested pull (needs tests) - sending comment to: " + comment_url)
+ commentOn(comment_url, True, False, True, resultsurl)
+ elif returncode != 0:
+ print("Failed to test pull - sending comment to: " + comment_url)
+ commentOn(comment_url, False, False, False, resultsurl)
+ else:
+ print("Successfully tested pull - sending comment to: " + comment_url)
+ commentOn(comment_url, True, False, False, resultsurl)
+ open(os.environ["TESTED_DB"], "a").write(commit + "\n")
+
+def environ_default(setting, value):
+ if not setting in os.environ:
+ os.environ[setting] = value
+
+if getpass.getuser() != "root":
+ print("Run me as root!")
+ sys.exit(1)
+
+if "GITHUB_USER" not in os.environ or "GITHUB_AUTH_TOKEN" not in os.environ:
+ print("GITHUB_USER and/or GITHUB_AUTH_TOKEN environment variables not set")
+ sys.exit(1)
+
+environ_default("CLONE_URL", "https://github.com/bitcoin/bitcoin.git")
+environ_default("MINGW_DEPS_DIR", "/mnt/w32deps")
+environ_default("SCRIPTS_DIR", "/mnt/test-scripts")
+environ_default("CHROOT_COPY", "/mnt/chroot-tmp")
+environ_default("CHROOT_MASTER", "/mnt/chroot")
+environ_default("OUT_DIR", "/mnt/out")
+environ_default("BUILD_PATH", "/mnt/bitcoin")
+os.environ["BUILD_DIR"] = os.environ["CHROOT_COPY"] + os.environ["BUILD_PATH"]
+environ_default("RESULTS_DIR", "/mnt/www/pull-tester")
+environ_default("RESULTS_URL", "http://jenkins.bluematt.me/pull-tester/")
+environ_default("GITHUB_REPO", "bitcoin/bitcoin")
+environ_default("TESTED_DB", "/mnt/commits-tested.txt")
+environ_default("BUILD_USER", "matt")
+environ_default("BUILD_GROUP", "matt")
+environ_default("TEST_TIMEOUT", str(60*60*2))
+
+print("Optional usage: pull-tester.py 2112")
+
+f = open(os.environ["TESTED_DB"])
+tested = set( line.rstrip() for line in f.readlines() )
+f.close()
+
+if len(sys.argv) > 1:
+ pull = requests.get("https://api.github.com/repos/"+os.environ["GITHUB_REPO"]+"/pulls/"+sys.argv[1],
+ auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])).json
+ testpull(pull["number"], pull["_links"]["comments"]["href"],
+ pull["head"]["repo"]["clone_url"], pull["head"]["sha"])
+
+else:
+ for page in range(1,100):
+ result = requests.get("https://api.github.com/repos/"+os.environ["GITHUB_REPO"]+"/pulls?state=open&page=%d"%(page,),
+ auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])).json
+ if len(result) == 0: break;
+ for pull in result:
+ if pull["head"]["sha"] in tested:
+ print("Pull %d already tested"%(pull["number"],))
+ continue
+ testpull(pull["number"], pull["_links"]["comments"]["href"],
+ pull["head"]["repo"]["clone_url"], pull["head"]["sha"])
diff --git a/qa/pull-tester/pull-tester.sh b/qa/pull-tester/pull-tester.sh
new file mode 100755
index 0000000000..13c800c16a
--- /dev/null
+++ b/qa/pull-tester/pull-tester.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Helper script for pull-tester.
+#Param 1: path to bitcoin srcroot
+#Param ...: arguments for build-test.sh
+
+if [ $# -lt 1 ]; then
+ echo "usage: $0 [bitcoin srcroot] build-test arguments..."
+fi
+
+cd $1
+shift
+
+./autogen.sh
+./configure
+./qa/pull-tester/build-tests.sh "$@"
diff --git a/qa/pull-tester/run-bitcoind-for-test.sh.in b/qa/pull-tester/run-bitcoind-for-test.sh.in
new file mode 100755
index 0000000000..e02fef3b56
--- /dev/null
+++ b/qa/pull-tester/run-bitcoind-for-test.sh.in
@@ -0,0 +1,27 @@
+#!/bin/bash
+DATADIR="@abs_top_builddir@/.bitcoin"
+rm -rf "$DATADIR"
+mkdir -p "$DATADIR"/regtest
+touch "$DATADIR/regtest/debug.log"
+tail -q -n 1 -F "$DATADIR/regtest/debug.log" | grep -m 1 -q "Done loading" &
+WAITER=$!
+"@abs_top_builddir@/src/bitcoind@EXEEXT@" -connect=0.0.0.0 -datadir="$DATADIR" -rpcuser=user -rpcpassword=pass -listen -keypool=3 -debug -logtimestamps -port=18444 -regtest &
+BITCOIND=$!
+
+#Install a watchdog.
+(sleep 10 && kill -0 $WAITER 2>/dev/null && kill -9 $BITCOIND $$)&
+wait $WAITER
+
+if [ -n "$TIMEOUT" ]; then
+ timeout "$TIMEOUT"s "$@"
+ RETURN=$?
+else
+ "$@"
+ RETURN=$?
+fi
+
+(sleep 15 && kill -0 $BITCOIND 2>/dev/null && kill -9 $BITCOIND $$)&
+kill $BITCOIND && wait $BITCOIND
+
+# timeout returns 124 on timeout, otherwise the return value of the child
+exit $RETURN
diff --git a/share/genbuild.sh b/share/genbuild.sh
index d959877dc8..da50b0d109 100755
--- a/share/genbuild.sh
+++ b/share/genbuild.sh
@@ -1,5 +1,7 @@
#!/bin/sh
-
+if [ $# -gt 1 ]; then
+ cd "$2"
+fi
if [ $# -gt 0 ]; then
FILE="$1"
shift
@@ -7,11 +9,11 @@ if [ $# -gt 0 ]; then
INFO="$(head -n 1 "$FILE")"
fi
else
- echo "Usage: $0 <filename>"
+ echo "Usage: $0 <filename> <srcroot>"
exit 1
fi
-if [ -e "$(which git)" ]; then
+if [ -e "$(which git)" -a -d ".git" ]; then
# clean 'dirty' status of touched files that haven't been modified
git diff >/dev/null 2>/dev/null
diff --git a/share/qt/Info.plist b/share/qt/Info.plist.in
index f191402e83..d0dd796561 100644
--- a/share/qt/Info.plist
+++ b/share/qt/Info.plist.in
@@ -7,11 +7,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleGetInfoString</key>
- <string>$VERSION, Copyright © 2009-$YEAR The Bitcoin developers</string>
+ <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@, Copyright © 2009-@COPYRIGHT_YEAR@ The Bitcoin developers</string>
<key>CFBundleShortVersionString</key>
- <string>$VERSION</string>
+ <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@</string>
<key>CFBundleVersion</key>
- <string>$VERSION</string>
+ <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>
diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py
index 1267b1856a..c9a96b21fe 100755
--- a/share/qt/extract_strings_qt.py
+++ b/share/qt/extract_strings_qt.py
@@ -6,6 +6,7 @@ they can be picked up by Qt linguist.
from subprocess import Popen, PIPE
import glob
import operator
+import os
OUT_CPP="src/qt/bitcoinstrings.cpp"
EMPTY=['""']
@@ -49,7 +50,8 @@ def parse_po(text):
files = glob.glob('src/*.cpp') + glob.glob('src/*.h')
# xgettext -n --keyword=_ $FILES
-child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE)
+XGETTEXT=os.getenv('XGETTEXT', 'xgettext')
+child = Popen([XGETTEXT,'--output=-','-n','--keyword=_'] + files, stdout=PIPE)
(out, err) = child.communicate()
messages = parse_po(out)
diff --git a/share/setup.nsi b/share/setup.nsi.in
index d5f2ffc3f8..dd37862382 100644
--- a/share/setup.nsi
+++ b/share/setup.nsi.in
@@ -1,162 +1,162 @@
-Name Bitcoin
-
-RequestExecutionLevel highest
-SetCompressor /SOLID lzma
-
-# General Symbol Definitions
-!define REGKEY "SOFTWARE\$(^Name)"
-!define VERSION 0.8.2
-!define COMPANY "Bitcoin project"
-!define URL http://www.bitcoin.org/
-
-# MUI Symbol Definitions
-!define MUI_ICON "../share/pixmaps/bitcoin.ico"
-!define MUI_WELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
-!define MUI_HEADERIMAGE
-!define MUI_HEADERIMAGE_RIGHT
-!define MUI_HEADERIMAGE_BITMAP "../share/pixmaps/nsis-header.bmp"
-!define MUI_FINISHPAGE_NOAUTOCLOSE
-!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
-!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
-!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
-!define MUI_STARTMENUPAGE_DEFAULTFOLDER Bitcoin
-!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin-qt.exe
-!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
-!define MUI_UNWELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
-!define MUI_UNFINISHPAGE_NOAUTOCLOSE
-
-# Included files
-!include Sections.nsh
-!include MUI2.nsh
-
-# Variables
-Var StartMenuGroup
-
-# Installer pages
-!insertmacro MUI_PAGE_WELCOME
-!insertmacro MUI_PAGE_DIRECTORY
-!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-
-# Installer languages
-!insertmacro MUI_LANGUAGE English
-
-# Installer attributes
-OutFile bitcoin-0.8.2-win32-setup.exe
-InstallDir $PROGRAMFILES\Bitcoin
-CRCCheck on
-XPStyle on
-BrandingText " "
-ShowInstDetails show
-VIProductVersion 0.8.2.2
-VIAddVersionKey ProductName Bitcoin
-VIAddVersionKey ProductVersion "${VERSION}"
-VIAddVersionKey CompanyName "${COMPANY}"
-VIAddVersionKey CompanyWebsite "${URL}"
-VIAddVersionKey FileVersion "${VERSION}"
-VIAddVersionKey FileDescription ""
-VIAddVersionKey LegalCopyright ""
-InstallDirRegKey HKCU "${REGKEY}" Path
-ShowUninstDetails show
-
-# Installer sections
-Section -Main SEC0000
- SetOutPath $INSTDIR
- SetOverwrite on
- File ../release/bitcoin-qt.exe
- File /oname=COPYING.txt ../COPYING
- File /oname=readme.txt ../doc/README_windows.txt
- SetOutPath $INSTDIR\daemon
- File ../src/bitcoind.exe
- SetOutPath $INSTDIR\src
- File /r /x *.exe /x *.o ../src\*.*
- SetOutPath $INSTDIR
- WriteRegStr HKCU "${REGKEY}\Components" Main 1
-
- # Remove old wxwidgets-based-bitcoin executable and locales:
- Delete /REBOOTOK $INSTDIR\bitcoin.exe
- RMDir /r /REBOOTOK $INSTDIR\locale
-SectionEnd
-
-Section -post SEC0001
- WriteRegStr HKCU "${REGKEY}" Path $INSTDIR
- SetOutPath $INSTDIR
- WriteUninstaller $INSTDIR\uninstall.exe
- !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
- CreateDirectory $SMPROGRAMS\$StartMenuGroup
- CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Bitcoin.lnk" $INSTDIR\bitcoin-qt.exe
- CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall Bitcoin.lnk" $INSTDIR\uninstall.exe
- !insertmacro MUI_STARTMENU_WRITE_END
- WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
- WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
- WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
- WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
- WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
- WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
- WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
- WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
- WriteRegStr HKCR "bitcoin" "URL Protocol" ""
- WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin"
- WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe
- WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "%1"'
-SectionEnd
-
-# Macro for selecting uninstaller sections
-!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
- Push $R0
- ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}"
- StrCmp $R0 1 0 next${UNSECTION_ID}
- !insertmacro SelectSection "${UNSECTION_ID}"
- GoTo done${UNSECTION_ID}
-next${UNSECTION_ID}:
- !insertmacro UnselectSection "${UNSECTION_ID}"
-done${UNSECTION_ID}:
- Pop $R0
-!macroend
-
-# Uninstaller sections
-Section /o -un.Main UNSEC0000
- Delete /REBOOTOK $INSTDIR\bitcoin-qt.exe
- Delete /REBOOTOK $INSTDIR\COPYING.txt
- Delete /REBOOTOK $INSTDIR\readme.txt
- RMDir /r /REBOOTOK $INSTDIR\daemon
- RMDir /r /REBOOTOK $INSTDIR\src
- DeleteRegValue HKCU "${REGKEY}\Components" Main
-SectionEnd
-
-Section -un.post UNSEC0001
- DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
- Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall Bitcoin.lnk"
- Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Bitcoin.lnk"
- Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk"
- Delete /REBOOTOK $INSTDIR\uninstall.exe
- Delete /REBOOTOK $INSTDIR\debug.log
- Delete /REBOOTOK $INSTDIR\db.log
- DeleteRegValue HKCU "${REGKEY}" StartMenuGroup
- DeleteRegValue HKCU "${REGKEY}" Path
- DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
- DeleteRegKey /IfEmpty HKCU "${REGKEY}"
- DeleteRegKey HKCR "bitcoin"
- RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
- RmDir /REBOOTOK $INSTDIR
- Push $R0
- StrCpy $R0 $StartMenuGroup 1
- StrCmp $R0 ">" no_smgroup
-no_smgroup:
- Pop $R0
-SectionEnd
-
-# Installer functions
-Function .onInit
- InitPluginsDir
-FunctionEnd
-
-# Uninstaller functions
-Function un.onInit
- ReadRegStr $INSTDIR HKCU "${REGKEY}" Path
- !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
- !insertmacro SELECT_UNSECTION Main ${UNSEC0000}
-FunctionEnd
+Name @PACKAGE_NAME@
+
+RequestExecutionLevel highest
+SetCompressor /SOLID lzma
+
+# General Symbol Definitions
+!define REGKEY "SOFTWARE\$(^Name)"
+!define VERSION @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@
+!define COMPANY "Bitcoin project"
+!define URL http://www.bitcoin.org/
+
+# MUI Symbol Definitions
+!define MUI_ICON "@abs_top_srcdir@/share/pixmaps/bitcoin.ico"
+!define MUI_WELCOMEFINISHPAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-wizard.bmp"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_RIGHT
+!define MUI_HEADERIMAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-header.bmp"
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
+!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
+!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
+!define MUI_STARTMENUPAGE_DEFAULTFOLDER @PACKAGE_NAME@
+!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin-qt.exe
+!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-wizard.bmp"
+!define MUI_UNFINISHPAGE_NOAUTOCLOSE
+
+# Included files
+!include Sections.nsh
+!include MUI2.nsh
+
+# Variables
+Var StartMenuGroup
+
+# Installer pages
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+
+# Installer languages
+!insertmacro MUI_LANGUAGE English
+
+# Installer attributes
+OutFile @abs_top_srcdir@/bitcoin-${VERSION}-win32-setup.exe
+InstallDir $PROGRAMFILES\Bitcoin
+CRCCheck on
+XPStyle on
+BrandingText " "
+ShowInstDetails show
+VIProductVersion ${VERSION}.@CLIENT_VERSION_BUILD@
+VIAddVersionKey ProductName Bitcoin
+VIAddVersionKey ProductVersion "${VERSION}"
+VIAddVersionKey CompanyName "${COMPANY}"
+VIAddVersionKey CompanyWebsite "${URL}"
+VIAddVersionKey FileVersion "${VERSION}"
+VIAddVersionKey FileDescription ""
+VIAddVersionKey LegalCopyright ""
+InstallDirRegKey HKCU "${REGKEY}" Path
+ShowUninstDetails show
+
+# Installer sections
+Section -Main SEC0000
+ SetOutPath $INSTDIR
+ SetOverwrite on
+ File @abs_top_srcdir@/release/bitcoin-qt.exe
+ File /oname=COPYING.txt @abs_top_srcdir@/COPYING
+ File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt
+ SetOutPath $INSTDIR\daemon
+ File @abs_top_srcdir@/release/bitcoind.exe
+ SetOutPath $INSTDIR\src
+ File /r @abs_top_srcdir@/@PACKAGE@-@VERSION@/src\*.*
+ SetOutPath $INSTDIR
+ WriteRegStr HKCU "${REGKEY}\Components" Main 1
+
+ # Remove old wxwidgets-based-bitcoin executable and locales:
+ Delete /REBOOTOK $INSTDIR\bitcoin.exe
+ RMDir /r /REBOOTOK $INSTDIR\locale
+SectionEnd
+
+Section -post SEC0001
+ WriteRegStr HKCU "${REGKEY}" Path $INSTDIR
+ SetOutPath $INSTDIR
+ WriteUninstaller $INSTDIR\uninstall.exe
+ !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+ CreateDirectory $SMPROGRAMS\$StartMenuGroup
+ CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Bitcoin.lnk" $INSTDIR\bitcoin-qt.exe
+ CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall Bitcoin.lnk" $INSTDIR\uninstall.exe
+ !insertmacro MUI_STARTMENU_WRITE_END
+ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
+ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
+ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
+ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
+ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
+ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
+ WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
+ WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
+ WriteRegStr HKCR "bitcoin" "URL Protocol" ""
+ WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin"
+ WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe
+ WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "%1"'
+SectionEnd
+
+# Macro for selecting uninstaller sections
+!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
+ Push $R0
+ ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}"
+ StrCmp $R0 1 0 next${UNSECTION_ID}
+ !insertmacro SelectSection "${UNSECTION_ID}"
+ GoTo done${UNSECTION_ID}
+next${UNSECTION_ID}:
+ !insertmacro UnselectSection "${UNSECTION_ID}"
+done${UNSECTION_ID}:
+ Pop $R0
+!macroend
+
+# Uninstaller sections
+Section /o -un.Main UNSEC0000
+ Delete /REBOOTOK $INSTDIR\bitcoin-qt.exe
+ Delete /REBOOTOK $INSTDIR\COPYING.txt
+ Delete /REBOOTOK $INSTDIR\readme.txt
+ RMDir /r /REBOOTOK $INSTDIR\daemon
+ RMDir /r /REBOOTOK $INSTDIR\src
+ DeleteRegValue HKCU "${REGKEY}\Components" Main
+SectionEnd
+
+Section -un.post UNSEC0001
+ DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
+ Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall Bitcoin.lnk"
+ Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Bitcoin.lnk"
+ Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk"
+ Delete /REBOOTOK $INSTDIR\uninstall.exe
+ Delete /REBOOTOK $INSTDIR\debug.log
+ Delete /REBOOTOK $INSTDIR\db.log
+ DeleteRegValue HKCU "${REGKEY}" StartMenuGroup
+ DeleteRegValue HKCU "${REGKEY}" Path
+ DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
+ DeleteRegKey /IfEmpty HKCU "${REGKEY}"
+ DeleteRegKey HKCR "bitcoin"
+ RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
+ RmDir /REBOOTOK $INSTDIR
+ Push $R0
+ StrCpy $R0 $StartMenuGroup 1
+ StrCmp $R0 ">" no_smgroup
+no_smgroup:
+ Pop $R0
+SectionEnd
+
+# Installer functions
+Function .onInit
+ InitPluginsDir
+FunctionEnd
+
+# Uninstaller functions
+Function un.onInit
+ ReadRegStr $INSTDIR HKCU "${REGKEY}" Path
+ !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
+ !insertmacro SELECT_UNSECTION Main ${UNSEC0000}
+FunctionEnd
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000000..c45f62adf5
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,3 @@
+
+test_bitcoin
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000000..49249fedc7
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,78 @@
+include Makefile.include
+AM_CPPFLAGS = $(INCLUDES) -I$(top_builddir)/src/obj \
+ -I$(top_srcdir)/src/leveldb/include -I$(top_srcdir)/src/leveldb/helpers \
+ -I$(builddir) $(BOOST_INCLUDES) $(BDB_CPPFLAGS)
+AM_LDFLAGS = $(PTHREAD_CFLAGS)
+
+noinst_LIBRARIES = libbitcoin.a
+
+bin_PROGRAMS = bitcoind
+
+SUBDIRS = . $(BUILD_QT) $(BUILD_TEST)
+DIST_SUBDIRS = . qt test
+.PHONY: FORCE
+# bitcoin core #
+BITCOIN_CORE_H = addrman.h alert.h allocators.h base58.h bignum.h \
+ bitcoinrpc.h bloom.h chainparams.h checkpoints.h checkqueue.h \
+ clientversion.h compat.h core.h crypter.h db.h hash.h init.h \
+ key.h keystore.h leveldb.h limitedmap.h main.h miner.h mruset.h \
+ netbase.h net.h protocol.h script.h serialize.h sync.h threadsafety.h \
+ txdb.h ui_interface.h uint256.h util.h version.h walletdb.h wallet.h
+
+JSON_H = json/json_spirit.h json/json_spirit_error_position.h \
+ json/json_spirit_reader.h json/json_spirit_reader_template.h \
+ json/json_spirit_stream_reader.h json/json_spirit_utils.h \
+ json/json_spirit_value.h json/json_spirit_writer.h \
+ json/json_spirit_writer_template.h
+
+obj/build.h: FORCE
+ @$(MKDIR_P) $(abs_top_builddir)/src/obj
+ @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
+ $(abs_top_srcdir)
+version.o: obj/build.h
+
+libbitcoin_a_SOURCES = addrman.cpp alert.cpp allocators.cpp bitcoinrpc.cpp bloom.cpp \
+ chainparams.cpp checkpoints.cpp core.cpp crypter.cpp db.cpp hash.cpp \
+ init.cpp key.cpp keystore.cpp leveldb.cpp main.cpp miner.cpp \
+ netbase.cpp net.cpp noui.cpp protocol.cpp rpcblockchain.cpp rpcdump.cpp \
+ rpcmining.cpp rpcnet.cpp rpcrawtransaction.cpp rpcwallet.cpp script.cpp \
+ sync.cpp txdb.cpp util.cpp version.cpp wallet.cpp walletdb.cpp $(JSON_H) \
+ $(BITCOIN_CORE_H)
+
+nodist_libbitcoin_a_SOURCES = $(top_srcdir)/src/obj/build.h
+#
+
+# bitcoind binary #
+bitcoind_LDADD = libbitcoin.a leveldb/libleveldb.a leveldb/libmemenv.a \
+ $(BOOST_LIBS)
+bitcoind_SOURCES = bitcoind.cpp
+#
+
+if TARGET_WINDOWS
+bitcoind_SOURCES += bitcoind-res.rc
+endif
+
+AM_CPPFLAGS += $(BDB_CPPFLAGS)
+bitcoind_LDADD += $(BDB_LIBS)
+
+leveldb/libleveldb.a: leveldb/libmemenv.a
+
+leveldb/%.a:
+ @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
+ CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
+ OPT="$(CXXFLAGS) $(CPPFLAGS)"
+
+qt/bitcoinstrings.cpp: $(libbitcoin_a_SOURCES)
+ @test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
+ @cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py
+
+CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno
+
+DISTCLEANFILES = obj/build.h
+
+EXTRA_DIST = leveldb Makefile.include
+
+clean-local:
+ -$(MAKE) -C leveldb clean
+ rm -f leveldb/port/*.gcno leveldb/db/*.gcno leveldb/table/*.gcno leveldb/helpers/*.gcno
+ rm -f leveldb/util/*.gcno leveldb/helpers/memenv/*.gcno
diff --git a/src/Makefile.include b/src/Makefile.include
new file mode 100644
index 0000000000..352471061d
--- /dev/null
+++ b/src/Makefile.include
@@ -0,0 +1,65 @@
+# Helper for rules and subdir Makefiles to find parent targets.
+# Flags and other non-target variables should not be set here.
+
+LIBBITCOIN=$(top_builddir)/src/libbitcoin.a
+LIBLEVELDB=$(top_builddir)/src/leveldb/libleveldb.a
+LIBMEMENV=$(top_builddir)/src/leveldb/libmemenv.a
+LIBBITCOINQT=$(top_builddir)/src/qt/libbitcoinqt.a
+
+$(LIBBITCOIN):
+ $(MAKE) -C $(top_builddir)/src $(@F)
+
+$(LIBLEVELDB) $(LIBMEMENV):
+ $(MAKE) -C $(top_builddir)/src leveldb/$(@F)
+
+$(LIBBITCOINQT):
+ $(MAKE) -C $(top_builddir)/src/qt $(@F)
+
+.mm.o:
+ $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $<
+
+.rc.o:
+ @test -f $(WINDRES) && $(WINDRES) -i $< -o $@ || \
+ echo error: could not build $@
+
+ui_%.h: %.ui
+ @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D)
+ @test -f $(UIC) && $(UIC) -o $(abs_builddir)/$@ $(abs_srcdir)/$< || echo error: could not build $(abs_builddir)/$@
+ $(SED) -i.bak -e '/^\*\*.*Created:/d' $(abs_builddir)/$@ && rm $(abs_builddir)/$@.bak
+ $(SED) -i.bak -e '/^\*\*.*by:/d' $(abs_builddir)/$@ && rm $(abs_builddir)/$@.bak
+
+%.moc: %.cpp
+ $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $<
+ $(SED) -i.bak -e '/^\*\*.*Created:/d' $@ && rm $@.bak
+ $(SED) -i.bak -e '/^\*\*.*by:/d' $@ && rm $@.bak
+
+moc_%.cpp: %.h
+ $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $<
+ $(SED) -i.bak -e '/^\*\*.*Created:/d' $@ && rm $@.bak
+ $(SED) -i.bak -e '/^\*\*.*by:/d' $@ && rm $@.bak
+
+%.qm: %.ts
+ @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D)
+ @test -f $(LRELEASE) && $(LRELEASE) $(abs_srcdir)/$< -qm $(abs_builddir)/$@ || \
+ echo error: could not build $(abs_builddir)/$@
+
+%.pb.cc %.pb.h: %.proto
+ test -f $(PROTOC) && $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<) || \
+ echo error: could not build $@
+
+%.json.h: %.json
+ @$(MKDIR_P) $(@D)
+ @echo "namespace json_tests{" > $@
+ @echo "static unsigned const char $(*F)[] = {" >> $@
+ @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
+ @echo "};};" >> $@
+ @echo "Generated $@"
+
+%.raw.h: %.raw
+ @$(MKDIR_P) $(@D)
+ @echo "namespace alert_tests{" > $@
+ @echo "static unsigned const char $(*F)[] = {" >> $@
+ @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
+ @echo "};};" >> $@
+ @echo "Generated $@"
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 780edde90f..731ff2abed 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -261,8 +261,6 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
void CAddrMan::Good_(const CService &addr, int64 nTime)
{
-// printf("Good: addr=%s\n", addr.ToString().c_str());
-
int nId;
CAddrInfo *pinfo = Find(addr, &nId);
@@ -304,7 +302,7 @@ void CAddrMan::Good_(const CService &addr, int64 nTime)
// TODO: maybe re-add the node, but for now, just bail out
if (nUBucket == -1) return;
- printf("Moving %s to tried\n", addr.ToString().c_str());
+ LogPrint("addrman", "Moving %s to tried\n", addr.ToString().c_str());
// move nId to the tried tables
MakeTried(info, nId, nUBucket);
@@ -351,7 +349,6 @@ bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePen
} else {
pinfo = Create(addr, source, &nId);
pinfo->nTime = max((int64)0, (int64)pinfo->nTime - nTimePenalty);
-// printf("Added %s [nTime=%fhr]\n", pinfo->ToString().c_str(), (GetAdjustedTime() - pinfo->nTime) / 3600.0);
nNew++;
fNew = true;
}
diff --git a/src/addrman.h b/src/addrman.h
index 7af6afd78f..081543ace4 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -403,7 +403,7 @@ public:
LOCK(cs);
int err;
if ((err=Check_()))
- printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
+ LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
}
#endif
}
@@ -419,7 +419,7 @@ public:
Check();
}
if (fRet)
- printf("Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew);
+ LogPrint("addr", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew);
return fRet;
}
@@ -435,7 +435,7 @@ public:
Check();
}
if (nAdd)
- printf("Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew);
+ LogPrint("addr", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew);
return nAdd > 0;
}
diff --git a/src/alert.cpp b/src/alert.cpp
index e00847aadb..c9cde17955 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -76,7 +76,7 @@ std::string CUnsignedAlert::ToString() const
void CUnsignedAlert::print() const
{
- printf("%s", ToString().c_str());
+ LogPrintf("%s", ToString().c_str());
}
void CAlert::SetNull()
@@ -200,13 +200,13 @@ bool CAlert::ProcessAlert(bool fThread)
const CAlert& alert = (*mi).second;
if (Cancels(alert))
{
- printf("cancelling alert %d\n", alert.nID);
+ LogPrint("alert", "cancelling alert %d\n", alert.nID);
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
mapAlerts.erase(mi++);
}
else if (!alert.IsInEffect())
{
- printf("expiring alert %d\n", alert.nID);
+ LogPrint("alert", "expiring alert %d\n", alert.nID);
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
mapAlerts.erase(mi++);
}
@@ -220,7 +220,7 @@ bool CAlert::ProcessAlert(bool fThread)
const CAlert& alert = item.second;
if (alert.Cancels(*this))
{
- printf("alert already cancelled by %d\n", alert.nID);
+ LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
return false;
}
}
@@ -258,6 +258,6 @@ bool CAlert::ProcessAlert(bool fThread)
}
}
- printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
+ LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
return true;
}
diff --git a/src/allocators.cpp b/src/allocators.cpp
new file mode 100644
index 0000000000..b239b623d8
--- /dev/null
+++ b/src/allocators.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2009-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "allocators.h"
+
+#ifdef WIN32
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0501
+#define WIN32_LEAN_AND_MEAN 1
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+// This is used to attempt to keep keying material out of swap
+// Note that VirtualLock does not provide this as a guarantee on Windows,
+// but, in practice, memory that has been VirtualLock'd almost never gets written to
+// the pagefile except in rare circumstances where memory is extremely low.
+#else
+#include <sys/mman.h>
+#include <limits.h> // for PAGESIZE
+#include <unistd.h> // for sysconf
+#endif
+
+/** Determine system page size in bytes */
+static inline size_t GetSystemPageSize()
+{
+ size_t page_size;
+#if defined(WIN32)
+ SYSTEM_INFO sSysInfo;
+ GetSystemInfo(&sSysInfo);
+ page_size = sSysInfo.dwPageSize;
+#elif defined(PAGESIZE) // defined in limits.h
+ page_size = PAGESIZE;
+#else // assume some POSIX OS
+ page_size = sysconf(_SC_PAGESIZE);
+#endif
+ return page_size;
+}
+
+bool MemoryPageLocker::Lock(const void *addr, size_t len)
+{
+#ifdef WIN32
+ return VirtualLock(const_cast<void*>(addr), len);
+#else
+ return mlock(addr, len) == 0;
+#endif
+}
+
+bool MemoryPageLocker::Unlock(const void *addr, size_t len)
+{
+#ifdef WIN32
+ return VirtualUnlock(const_cast<void*>(addr), len);
+#else
+ return munlock(addr, len) == 0;
+#endif
+}
+
+LockedPageManager::LockedPageManager() : LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize())
+{
+}
+
diff --git a/src/allocators.h b/src/allocators.h
index 85af8fe376..fd6f51b27e 100644
--- a/src/allocators.h
+++ b/src/allocators.h
@@ -11,25 +11,6 @@
#include <map>
#include <openssl/crypto.h> // for OPENSSL_cleanse()
-#ifdef WIN32
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0501
-#define WIN32_LEAN_AND_MEAN 1
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <windows.h>
-// This is used to attempt to keep keying material out of swap
-// Note that VirtualLock does not provide this as a guarantee on Windows,
-// but, in practice, memory that has been VirtualLock'd almost never gets written to
-// the pagefile except in rare circumstances where memory is extremely low.
-#else
-#include <sys/mman.h>
-#include <limits.h> // for PAGESIZE
-#include <unistd.h> // for sysconf
-#endif
/**
* Thread-safe class to keep track of locked (ie, non-swappable) memory pages.
@@ -115,21 +96,6 @@ private:
Histogram histogram;
};
-/** Determine system page size in bytes */
-static inline size_t GetSystemPageSize()
-{
- size_t page_size;
-#if defined(WIN32)
- SYSTEM_INFO sSysInfo;
- GetSystemInfo(&sSysInfo);
- page_size = sSysInfo.dwPageSize;
-#elif defined(PAGESIZE) // defined in limits.h
- page_size = PAGESIZE;
-#else // assume some POSIX OS
- page_size = sysconf(_SC_PAGESIZE);
-#endif
- return page_size;
-}
/**
* OS-dependent memory page locking/unlocking.
@@ -141,25 +107,11 @@ public:
/** Lock memory pages.
* addr and len must be a multiple of the system page size
*/
- bool Lock(const void *addr, size_t len)
- {
-#ifdef WIN32
- return VirtualLock(const_cast<void*>(addr), len);
-#else
- return mlock(addr, len) == 0;
-#endif
- }
+ bool Lock(const void *addr, size_t len);
/** Unlock memory pages.
* addr and len must be a multiple of the system page size
*/
- bool Unlock(const void *addr, size_t len)
- {
-#ifdef WIN32
- return VirtualUnlock(const_cast<void*>(addr), len);
-#else
- return munlock(addr, len) == 0;
-#endif
- }
+ bool Unlock(const void *addr, size_t len);
};
/**
@@ -171,9 +123,7 @@ class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
public:
static LockedPageManager instance; // instantiated in util.cpp
private:
- LockedPageManager():
- LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize())
- {}
+ LockedPageManager();
};
//
diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc
new file mode 100644
index 0000000000..202b7ab352
--- /dev/null
+++ b/src/bitcoind-res.rc
@@ -0,0 +1,36 @@
+#include <windows.h> // needed for VERSIONINFO
+#include "clientversion.h" // holds the needed client version information
+
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_FILEVERSION VER_PRODUCTVERSION
+#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
+#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin developers"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4" // U.S. English - multilingual (hex)
+ BEGIN
+ VALUE "CompanyName", "Bitcoin"
+ VALUE "FileDescription", "Bitcoind (OSS daemon/client for Bitcoin)"
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", "bitcoind"
+ VALUE "LegalCopyright", COPYRIGHT_STR
+ VALUE "LegalTrademarks1", "Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php."
+ VALUE "OriginalFilename", "bitcoind.exe"
+ VALUE "ProductName", "Bitcoind"
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal)
+ END
+END
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 02e4e7d6e7..add3b4e1f0 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -9,15 +9,18 @@
void DetectShutdownThread(boost::thread_group* threadGroup)
{
- bool shutdown = ShutdownRequested();
+ bool fShutdown = ShutdownRequested();
// Tell the main threads to shutdown.
- while (!shutdown)
+ while (!fShutdown)
{
MilliSleep(200);
- shutdown = ShutdownRequested();
+ fShutdown = ShutdownRequested();
}
if (threadGroup)
+ {
threadGroup->interrupt_all();
+ threadGroup->join_all();
+ }
}
//////////////////////////////////////////////////////////////////////////////
@@ -66,6 +69,7 @@ bool AppInit(int argc, char* argv[])
}
// Command-line RPC
+ bool fCommandLine = false;
for (int i = 1; i < argc; i++)
if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
fCommandLine = true;
@@ -107,10 +111,16 @@ bool AppInit(int argc, char* argv[])
} catch (...) {
PrintExceptionContinue(NULL, "AppInit()");
}
- if (!fRet) {
+
+ if (!fRet)
+ {
if (detectShutdownThread)
detectShutdownThread->interrupt();
+
threadGroup.interrupt_all();
+ // threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
+ // the startup-failure cases to make sure they don't result in a hang due to some
+ // thread-blocking-waiting-for-another-thread-during-startup case
}
if (detectShutdownThread)
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index d22809ce69..798660dff3 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -113,6 +113,34 @@ std::string HexBits(unsigned int nBits)
return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
}
+uint256 ParseHashV(const Value& v, string strName)
+{
+ string strHex;
+ if (v.type() == str_type)
+ strHex = v.get_str();
+ if (!IsHex(strHex)) // Note: IsHex("") is false
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
+ uint256 result;
+ result.SetHex(strHex);
+ return result;
+}
+uint256 ParseHashO(const Object& o, string strKey)
+{
+ return ParseHashV(find_value(o, strKey), strKey);
+}
+vector<unsigned char> ParseHexV(const Value& v, string strName)
+{
+ string strHex;
+ if (v.type() == str_type)
+ strHex = v.get_str();
+ if (!IsHex(strHex))
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
+ return ParseHex(strHex);
+}
+vector<unsigned char> ParseHexO(const Object& o, string strKey)
+{
+ return ParseHexV(find_value(o, strKey), strKey);
+}
///
@@ -132,6 +160,9 @@ string CRPCTable::help(string strCommand) const
continue;
if (strCommand != "" && strMethod != strCommand)
continue;
+ if (pcmd->reqWallet && !pwalletMain)
+ continue;
+
try
{
Array params;
@@ -190,74 +221,79 @@ Value stop(const Array& params, bool fHelp)
static const CRPCCommand vRPCCommands[] =
-{ // name actor (function) okSafeMode threadSafe
- // ------------------------ ----------------------- ---------- ----------
- { "help", &help, true, true },
- { "stop", &stop, true, true },
- { "getblockcount", &getblockcount, true, false },
- { "getbestblockhash", &getbestblockhash, true, false },
- { "getconnectioncount", &getconnectioncount, true, false },
- { "getpeerinfo", &getpeerinfo, true, false },
- { "addnode", &addnode, true, true },
- { "getaddednodeinfo", &getaddednodeinfo, true, true },
- { "getdifficulty", &getdifficulty, true, false },
- { "getgenerate", &getgenerate, true, false },
- { "setgenerate", &setgenerate, true, false },
- { "gethashespersec", &gethashespersec, true, false },
- { "getinfo", &getinfo, true, false },
- { "getmininginfo", &getmininginfo, true, false },
- { "getnewaddress", &getnewaddress, true, false },
- { "getaccountaddress", &getaccountaddress, true, false },
- { "setaccount", &setaccount, true, false },
- { "getaccount", &getaccount, false, false },
- { "getaddressesbyaccount", &getaddressesbyaccount, true, false },
- { "sendtoaddress", &sendtoaddress, false, false },
- { "getreceivedbyaddress", &getreceivedbyaddress, false, false },
- { "getreceivedbyaccount", &getreceivedbyaccount, false, false },
- { "listreceivedbyaddress", &listreceivedbyaddress, false, false },
- { "listreceivedbyaccount", &listreceivedbyaccount, false, false },
- { "backupwallet", &backupwallet, true, false },
- { "keypoolrefill", &keypoolrefill, true, false },
- { "walletpassphrase", &walletpassphrase, true, false },
- { "walletpassphrasechange", &walletpassphrasechange, false, false },
- { "walletlock", &walletlock, true, false },
- { "encryptwallet", &encryptwallet, false, false },
- { "validateaddress", &validateaddress, true, false },
- { "getbalance", &getbalance, false, false },
- { "move", &movecmd, false, false },
- { "sendfrom", &sendfrom, false, false },
- { "sendmany", &sendmany, false, false },
- { "addmultisigaddress", &addmultisigaddress, false, false },
- { "createmultisig", &createmultisig, true, true },
- { "getrawmempool", &getrawmempool, true, false },
- { "getblock", &getblock, false, false },
- { "getblockhash", &getblockhash, false, false },
- { "gettransaction", &gettransaction, false, false },
- { "listtransactions", &listtransactions, false, false },
- { "listaddressgroupings", &listaddressgroupings, false, false },
- { "signmessage", &signmessage, false, false },
- { "verifymessage", &verifymessage, false, false },
- { "getwork", &getwork, true, false },
- { "listaccounts", &listaccounts, false, false },
- { "settxfee", &settxfee, false, false },
- { "getblocktemplate", &getblocktemplate, true, false },
- { "submitblock", &submitblock, false, false },
- { "listsinceblock", &listsinceblock, false, false },
- { "dumpprivkey", &dumpprivkey, true, false },
- { "dumpwallet", &dumpwallet, true, false },
- { "importprivkey", &importprivkey, false, false },
- { "importwallet", &importwallet, false, false },
- { "listunspent", &listunspent, false, false },
- { "getrawtransaction", &getrawtransaction, false, false },
- { "createrawtransaction", &createrawtransaction, false, false },
- { "decoderawtransaction", &decoderawtransaction, false, false },
- { "signrawtransaction", &signrawtransaction, false, false },
- { "sendrawtransaction", &sendrawtransaction, false, false },
- { "gettxoutsetinfo", &gettxoutsetinfo, true, false },
- { "gettxout", &gettxout, true, false },
- { "lockunspent", &lockunspent, false, false },
- { "listlockunspent", &listlockunspent, false, false },
- { "verifychain", &verifychain, true, false },
+{ // name actor (function) okSafeMode threadSafe reqWallet
+ // ------------------------ ----------------------- ---------- ---------- ---------
+ { "help", &help, true, true, false },
+ { "stop", &stop, true, true, false },
+ { "getblockcount", &getblockcount, true, false, false },
+ { "getbestblockhash", &getbestblockhash, true, false, false },
+ { "getconnectioncount", &getconnectioncount, true, false, false },
+ { "getpeerinfo", &getpeerinfo, true, false, false },
+ { "ping", &ping, true, false, false },
+ { "addnode", &addnode, true, true, false },
+ { "getaddednodeinfo", &getaddednodeinfo, true, true, false },
+ { "getnettotals", &getnettotals, true, true, false },
+ { "getdifficulty", &getdifficulty, true, false, false },
+ { "getnetworkhashps", &getnetworkhashps, true, false, false },
+ { "getgenerate", &getgenerate, true, false, false },
+ { "setgenerate", &setgenerate, true, false, true },
+ { "gethashespersec", &gethashespersec, true, false, false },
+ { "getinfo", &getinfo, true, false, false },
+ { "getmininginfo", &getmininginfo, true, false, false },
+ { "getnewaddress", &getnewaddress, true, false, true },
+ { "getaccountaddress", &getaccountaddress, true, false, true },
+ { "getrawchangeaddress", &getrawchangeaddress, true, false, true },
+ { "setaccount", &setaccount, true, false, true },
+ { "getaccount", &getaccount, false, false, true },
+ { "getaddressesbyaccount", &getaddressesbyaccount, true, false, true },
+ { "sendtoaddress", &sendtoaddress, false, false, true },
+ { "getreceivedbyaddress", &getreceivedbyaddress, false, false, true },
+ { "getreceivedbyaccount", &getreceivedbyaccount, false, false, true },
+ { "listreceivedbyaddress", &listreceivedbyaddress, false, false, true },
+ { "listreceivedbyaccount", &listreceivedbyaccount, false, false, true },
+ { "backupwallet", &backupwallet, true, false, true },
+ { "keypoolrefill", &keypoolrefill, true, false, true },
+ { "walletpassphrase", &walletpassphrase, true, false, true },
+ { "walletpassphrasechange", &walletpassphrasechange, false, false, true },
+ { "walletlock", &walletlock, true, false, true },
+ { "encryptwallet", &encryptwallet, false, false, true },
+ { "validateaddress", &validateaddress, true, false, false },
+ { "getbalance", &getbalance, false, false, true },
+ { "move", &movecmd, false, false, true },
+ { "sendfrom", &sendfrom, false, false, true },
+ { "sendmany", &sendmany, false, false, true },
+ { "addmultisigaddress", &addmultisigaddress, false, false, true },
+ { "createmultisig", &createmultisig, true, true , false },
+ { "getrawmempool", &getrawmempool, true, false, false },
+ { "getblock", &getblock, false, false, false },
+ { "getblockhash", &getblockhash, false, false, false },
+ { "gettransaction", &gettransaction, false, false, true },
+ { "listtransactions", &listtransactions, false, false, true },
+ { "listaddressgroupings", &listaddressgroupings, false, false, true },
+ { "signmessage", &signmessage, false, false, true },
+ { "verifymessage", &verifymessage, false, false, false },
+ { "getwork", &getwork, true, false, true },
+ { "listaccounts", &listaccounts, false, false, true },
+ { "settxfee", &settxfee, false, false, true },
+ { "getblocktemplate", &getblocktemplate, true, false, false },
+ { "submitblock", &submitblock, false, false, false },
+ { "listsinceblock", &listsinceblock, false, false, true },
+ { "dumpprivkey", &dumpprivkey, true, false, true },
+ { "dumpwallet", &dumpwallet, true, false, true },
+ { "importprivkey", &importprivkey, false, false, true },
+ { "importwallet", &importwallet, false, false, true },
+ { "listunspent", &listunspent, false, false, true },
+ { "getrawtransaction", &getrawtransaction, false, false, false },
+ { "createrawtransaction", &createrawtransaction, false, false, false },
+ { "decoderawtransaction", &decoderawtransaction, false, false, false },
+ { "decodescript", &decodescript, false, false, false },
+ { "signrawtransaction", &signrawtransaction, false, false, false },
+ { "sendrawtransaction", &sendrawtransaction, false, false, false },
+ { "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
+ { "gettxout", &gettxout, true, false, false },
+ { "lockunspent", &lockunspent, false, false, true },
+ { "listlockunspent", &listlockunspent, false, false, true },
+ { "verifychain", &verifychain, true, false, false },
};
CRPCTable::CRPCTable()
@@ -766,12 +802,12 @@ void StartRPCThreads()
filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
if (filesystem::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string());
- else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
+ else LogPrintf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
if (filesystem::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem);
- else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
+ else LogPrintf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
SSL_CTX_set_cipher_list(rpc_ssl_context->impl(), strCiphers.c_str());
@@ -846,7 +882,8 @@ void StopRPCThreads()
deadlineTimers.clear();
rpc_io_service->stop();
- rpc_worker_group->join_all();
+ if (rpc_worker_group != NULL)
+ rpc_worker_group->join_all();
delete rpc_worker_group; rpc_worker_group = NULL;
delete rpc_ssl_context; rpc_ssl_context = NULL;
delete rpc_io_service; rpc_io_service = NULL;
@@ -901,7 +938,7 @@ void JSONRequest::parse(const Value& valRequest)
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getwork" && strMethod != "getblocktemplate")
- printf("ThreadRPCServer method=%s\n", strMethod.c_str());
+ LogPrint("rpc", "ThreadRPCServer method=%s\n", strMethod.c_str());
// Parse params
Value valParams = find_value(request, "params");
@@ -975,10 +1012,10 @@ void ServiceConnection(AcceptedConnection *conn)
}
if (!HTTPAuthorized(mapHeaders))
{
- printf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string().c_str());
+ LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string().c_str());
/* Deter brute-forcing short passwords.
- If this results in a DOS the user really
- shouldn't have their RPC port exposed.*/
+ If this results in a DoS the user really
+ shouldn't have their RPC port exposed. */
if (mapArgs["-rpcpassword"].size() < 20)
MilliSleep(250);
@@ -1034,6 +1071,8 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
const CRPCCommand *pcmd = tableRPC[strMethod];
if (!pcmd)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
+ if (pcmd->reqWallet && !pwalletMain)
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
// Observe safe mode
string strWarning = GetWarnings("rpc");
@@ -1048,7 +1087,10 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
{
if (pcmd->threadSafe)
result = pcmd->actor(params, false);
- else {
+ else if (!pwalletMain) {
+ LOCK(cs_main);
+ result = pcmd->actor(params, false);
+ } else {
LOCK2(cs_main, pwalletMain->cs_wallet);
result = pcmd->actor(params, false);
}
@@ -1158,6 +1200,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "getnetworkhashps" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "getnetworkhashps" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
@@ -1193,6 +1237,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true);
+ if (strMethod == "sendrawtransaction" && n > 1) ConvertTo<bool>(params[1], true);
if (strMethod == "gettxout" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]);
if (strMethod == "lockunspent" && n > 0) ConvertTo<bool>(params[0]);
@@ -1289,7 +1334,7 @@ int main(int argc, char *argv[])
{
if (argc >= 2 && string(argv[1]) == "-server")
{
- printf("server ready\n");
+ LogPrintf("server ready\n");
ThreadRPCServer(NULL);
}
else
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 4d5599be84..1cad12f14a 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -104,6 +104,7 @@ public:
rpcfn_type actor;
bool okSafeMode;
bool threadSafe;
+ bool reqWallet;
};
/**
@@ -130,6 +131,15 @@ public:
extern const CRPCTable tableRPC;
+//
+// Utilities: convert hex-encoded Values
+// (throws error if not hex).
+//
+extern uint256 ParseHashV(const json_spirit::Value& v, std::string strName);
+extern uint256 ParseHashO(const json_spirit::Object& o, std::string strKey);
+extern std::vector<unsigned char> ParseHexV(const json_spirit::Value& v, std::string strName);
+extern std::vector<unsigned char> ParseHexO(const json_spirit::Object& o, std::string strKey);
+
extern void InitRPCMining();
extern void ShutdownRPCMining();
@@ -143,8 +153,10 @@ extern void EnsureWalletIsUnlocked();
extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp
extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
@@ -153,6 +165,7 @@ extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fH
extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp
extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp);
@@ -161,6 +174,7 @@ extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHe
extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp
extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value getrawchangeaddress(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value setaccount(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getaccount(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getaddressesbyaccount(const json_spirit::Array& params, bool fHelp);
@@ -197,6 +211,7 @@ extern json_spirit::Value lockunspent(const json_spirit::Array& params, bool fHe
extern json_spirit::Value listlockunspent(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value decodescript(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp);
diff --git a/src/chainparams.h b/src/chainparams.h
index ce3c14306d..3f99b7eb06 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -68,7 +68,7 @@ public:
virtual const vector<CAddress>& FixedSeeds() const = 0;
int RPCPort() const { return nRPCPort; }
protected:
- CChainParams() {};
+ CChainParams() {}
uint256 hashGenesisBlock;
MessageStartChars pchMessageStart;
diff --git a/src/clientversion.h b/src/clientversion.h
index 30c0c4072b..b376a67c8a 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -1,6 +1,9 @@
#ifndef CLIENTVERSION_H
#define CLIENTVERSION_H
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#else
//
// client versioning and copyright year
//
@@ -18,6 +21,8 @@
// Todo: update this when changing our copyright comments in the source
#define COPYRIGHT_YEAR 2013
+#endif //HAVE_CONFIG_H
+
// Converts the parameter X to a string after macro replacement on X has been performed.
// Don't merge these into one macro!
#define STRINGIZE(X) DO_STRINGIZE(X)
diff --git a/src/compat.h b/src/compat.h
index 4e98b46c1c..b126df901a 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -6,11 +6,17 @@
#define _BITCOIN_COMPAT_H
#ifdef WIN32
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
+#ifdef FD_SETSIZE
+#undef FD_SETSIZE // prevent redefinition compiler warning
+#endif
#define FD_SETSIZE 1024 // max number of fds in fd_set
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -26,7 +32,6 @@
#endif
#ifdef WIN32
-#define MSG_NOSIGNAL 0
#define MSG_DONTWAIT 0
#else
typedef u_int SOCKET;
diff --git a/src/core.cpp b/src/core.cpp
index afba0959cf..99b5c6641a 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -13,7 +13,7 @@ std::string COutPoint::ToString() const
void COutPoint::print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, unsigned int nSequenceIn)
@@ -47,7 +47,7 @@ std::string CTxIn::ToString() const
void CTxIn::print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
CTxOut::CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
@@ -70,7 +70,7 @@ std::string CTxOut::ToString() const
void CTxOut::print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
uint256 CTransaction::GetHash() const
@@ -125,7 +125,7 @@ std::string CTransaction::ToString() const
void CTransaction::print() const
{
- printf("%s", ToString().c_str());
+ LogPrintf("%s", ToString().c_str());
}
// Amount compression:
@@ -282,7 +282,7 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMer
void CBlock::print() const
{
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
+ LogPrintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
GetHash().ToString().c_str(),
nVersion,
hashPrevBlock.ToString().c_str(),
@@ -291,11 +291,11 @@ void CBlock::print() const
vtx.size());
for (unsigned int i = 0; i < vtx.size(); i++)
{
- printf(" ");
+ LogPrintf(" ");
vtx[i].print();
}
- printf(" vMerkleTree: ");
+ LogPrintf(" vMerkleTree: ");
for (unsigned int i = 0; i < vMerkleTree.size(); i++)
- printf("%s ", vMerkleTree[i].ToString().c_str());
- printf("\n");
+ LogPrintf("%s ", vMerkleTree[i].ToString().c_str());
+ LogPrintf("\n");
}
diff --git a/src/core.h b/src/core.h
index 1b9d4dd765..9ee8b2edce 100644
--- a/src/core.h
+++ b/src/core.h
@@ -389,7 +389,9 @@ public:
int nVersion;
// construct a CCoins from a CTransaction, at a given height
- CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) { }
+ CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) {
+ ClearUnspendable();
+ }
// empty constructor
CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { }
@@ -402,6 +404,14 @@ public:
std::vector<CTxOut>().swap(vout);
}
+ void ClearUnspendable() {
+ BOOST_FOREACH(CTxOut &txout, vout) {
+ if (txout.scriptPubKey.IsUnspendable())
+ txout.SetNull();
+ }
+ Cleanup();
+ }
+
void swap(CCoins &to) {
std::swap(to.fCoinBase, fCoinBase);
to.vout.swap(vout);
@@ -651,4 +661,38 @@ public:
void print() const;
};
+
+/** Describes a place in the block chain to another node such that if the
+ * other node doesn't have the same branch, it can find a recent common trunk.
+ * The further back it is, the further before the fork it may be.
+ */
+struct CBlockLocator
+{
+ std::vector<uint256> vHave;
+
+ CBlockLocator() {}
+
+ CBlockLocator(const std::vector<uint256>& vHaveIn)
+ {
+ vHave = vHaveIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ if (!(nType & SER_GETHASH))
+ READWRITE(nVersion);
+ READWRITE(vHave);
+ )
+
+ void SetNull()
+ {
+ vHave.clear();
+ }
+
+ bool IsNull()
+ {
+ return vHave.empty();
+ }
+};
+
#endif
diff --git a/src/db.cpp b/src/db.cpp
index 03f46f3c26..f722c52e93 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -38,7 +38,7 @@ void CDBEnv::EnvShutdown()
fDbEnvInit = false;
int ret = dbenv.close(0);
if (ret != 0)
- printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
+ LogPrintf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
if (!fMockDb)
DbEnv(0).remove(path.string().c_str(), 0);
}
@@ -70,7 +70,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn)
filesystem::path pathLogDir = path / "database";
filesystem::create_directory(pathLogDir);
filesystem::path pathErrorFile = path / "db.log";
- printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
+ LogPrintf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
unsigned int nEnvFlags = 0;
if (GetBoolArg("-privdb", true))
@@ -111,7 +111,7 @@ void CDBEnv::MakeMock()
boost::this_thread::interruption_point();
- printf("CDBEnv::MakeMock()\n");
+ LogPrint("db", "CDBEnv::MakeMock()\n");
dbenv.set_cachesize(1, 0, 1);
dbenv.set_lg_bsize(10485760*4);
@@ -168,16 +168,16 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive,
int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
if (result == DB_VERIFY_BAD)
{
- printf("Error: Salvage found errors, all data may not be recoverable.\n");
+ LogPrintf("Error: Salvage found errors, all data may not be recoverable.\n");
if (!fAggressive)
{
- printf("Error: Rerun with aggressive mode to ignore errors and continue.\n");
+ LogPrintf("Error: Rerun with aggressive mode to ignore errors and continue.\n");
return false;
}
}
if (result != 0 && result != DB_VERIFY_BAD)
{
- printf("ERROR: db salvage failed: %d\n",result);
+ LogPrintf("ERROR: db salvage failed: %d\n",result);
return false;
}
@@ -348,7 +348,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
bitdb.mapFileUseCount.erase(strFile);
bool fSuccess = true;
- printf("Rewriting %s...\n", strFile.c_str());
+ LogPrintf("Rewriting %s...\n", strFile.c_str());
string strFileRes = strFile + ".rewrite";
{ // surround usage of db with extra {}
CDB db(strFile.c_str(), "r");
@@ -362,7 +362,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
0);
if (ret > 0)
{
- printf("Cannot create database file %s\n", strFileRes.c_str());
+ LogPrintf("Cannot create database file %s\n", strFileRes.c_str());
fSuccess = false;
}
@@ -418,7 +418,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
fSuccess = false;
}
if (!fSuccess)
- printf("Rewriting of %s FAILED!\n", strFileRes.c_str());
+ LogPrintf("Rewriting of %s FAILED!\n", strFileRes.c_str());
return fSuccess;
}
}
@@ -433,7 +433,7 @@ void CDBEnv::Flush(bool fShutdown)
int64 nStart = GetTimeMillis();
// Flush log data to the actual data file
// on all files that are not in use
- printf("Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
+ LogPrint("db", "Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
if (!fDbEnvInit)
return;
{
@@ -443,23 +443,23 @@ void CDBEnv::Flush(bool fShutdown)
{
string strFile = (*mi).first;
int nRefCount = (*mi).second;
- printf("%s refcount=%d\n", strFile.c_str(), nRefCount);
+ LogPrint("db", "%s refcount=%d\n", strFile.c_str(), nRefCount);
if (nRefCount == 0)
{
// Move log data to the dat file
CloseDb(strFile);
- printf("%s checkpoint\n", strFile.c_str());
+ LogPrint("db", "%s checkpoint\n", strFile.c_str());
dbenv.txn_checkpoint(0, 0, 0);
- printf("%s detach\n", strFile.c_str());
+ LogPrint("db", "%s detach\n", strFile.c_str());
if (!fMockDb)
dbenv.lsn_reset(strFile.c_str(), 0);
- printf("%s closed\n", strFile.c_str());
+ LogPrint("db", "%s closed\n", strFile.c_str());
mapFileUseCount.erase(mi++);
}
else
mi++;
}
- printf("DBFlush(%s)%s ended %15"PRI64d"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
+ LogPrint("db", "DBFlush(%s)%s ended %15"PRI64d"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
if (fShutdown)
{
char** listp;
diff --git a/src/db.h b/src/db.h
index b3f269f3da..8736031da4 100644
--- a/src/db.h
+++ b/src/db.h
@@ -16,7 +16,7 @@
#include <db_cxx.h>
class CAddrMan;
-class CBlockLocator;
+struct CBlockLocator;
class CDiskBlockIndex;
class CMasterKey;
class COutPoint;
diff --git a/src/init.cpp b/src/init.cpp
index acf6deab8d..fce5992255 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -3,6 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "init.h"
#include "main.h"
#include "core.h"
@@ -96,6 +100,7 @@ static CCoinsViewDB *pcoinsdbview;
void Shutdown()
{
+ LogPrintf("Shutdown : In progress...\n");
static CCriticalSection cs_Shutdown;
TRY_LOCK(cs_Shutdown, lockShutdown);
if (!lockShutdown) return;
@@ -104,13 +109,14 @@ void Shutdown()
nTransactionsUpdated++;
StopRPCThreads();
ShutdownRPCMining();
- bitdb.Flush(false);
+ if (pwalletMain)
+ bitdb.Flush(false);
GenerateBitcoins(false, NULL);
StopNode();
{
LOCK(cs_main);
if (pwalletMain)
- pwalletMain->SetBestChain(CBlockLocator(pindexBest));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
if (pblocktree)
pblocktree->Flush();
if (pcoinsTip)
@@ -119,10 +125,13 @@ void Shutdown()
delete pcoinsdbview; pcoinsdbview = NULL;
delete pblocktree; pblocktree = NULL;
}
- bitdb.Flush(true);
+ if (pwalletMain)
+ bitdb.Flush(true);
boost::filesystem::remove(GetPidFile());
UnregisterAllWallets();
- delete pwalletMain;
+ if (pwalletMain)
+ delete pwalletMain;
+ LogPrintf("Shutdown : done\n");
}
//
@@ -280,13 +289,13 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
FILE *file = OpenBlockFile(pos, true);
if (!file)
break;
- printf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
+ LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
LoadExternalBlockFile(file, &pos);
nFile++;
}
pblocktree->WriteReindexing(false);
fReindex = false;
- printf("Reindexing finished\n");
+ LogPrintf("Reindexing finished\n");
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
InitBlockIndex();
}
@@ -298,7 +307,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
if (file) {
CImportingNow imp;
filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
- printf("Importing bootstrap.dat...\n");
+ LogPrintf("Importing bootstrap.dat...\n");
LoadExternalBlockFile(file);
RenameOver(pathBootstrap, pathBootstrapOld);
}
@@ -309,7 +318,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
FILE *file = fopen(path.string().c_str(), "rb");
if (file) {
CImportingNow imp;
- printf("Importing %s...\n", path.string().c_str());
+ LogPrintf("Importing %s...\n", path.string().c_str());
LoadExternalBlockFile(file);
}
}
@@ -335,8 +344,8 @@ bool AppInit2(boost::thread_group& threadGroup)
// Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
// A failure is non-critical and needs no further attention!
#ifndef PROCESS_DEP_ENABLE
-// We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
-// which is not correct. Can be removed, when GCCs winbase.h is fixed!
+ // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
+ // which is not correct. Can be removed, when GCCs winbase.h is fixed!
#define PROCESS_DEP_ENABLE 0x00000001
#endif
typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD);
@@ -377,8 +386,6 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 2: parameter interactions
- Checkpoints::fEnabled = GetBoolArg("-checkpoints", true);
-
if (mapArgs.count("-bind")) {
// when specifying an explicit binding address, you want to listen on it
// even when -connect or -proxy is specified
@@ -424,9 +431,10 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 3: parameter-to-internal-flags
- fDebug = GetBoolArg("-debug", false);
+ if (mapMultiArgs.count("-debug")) fDebug = true;
fBenchmark = GetBoolArg("-benchmark", false);
mempool.fChecks = GetBoolArg("-checkmempool", RegTest());
+ Checkpoints::fEnabled = GetBoolArg("-checkpoints", true);
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
nScriptCheckThreads = GetArg("-par", 0);
@@ -519,21 +527,21 @@ bool AppInit2(boost::thread_group& threadGroup)
if (GetBoolArg("-shrinkdebugfile", !fDebug))
ShrinkDebugFile();
- printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
- printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str());
- printf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
+ LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+ LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str());
+ LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
if (!fLogTimestamps)
- printf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
- printf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
- printf("Using data directory %s\n", strDataDir.c_str());
- printf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
+ LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
+ LogPrintf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
+ LogPrintf("Using data directory %s\n", strDataDir.c_str());
+ LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
std::ostringstream strErrors;
if (fDaemon)
fprintf(stdout, "Bitcoin server starting\n");
if (nScriptCheckThreads) {
- printf("Using %u threads for script verification\n", nScriptCheckThreads);
+ LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
for (int i=0; i<nScriptCheckThreads-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
}
@@ -551,7 +559,7 @@ bool AppInit2(boost::thread_group& threadGroup)
boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%"PRI64d".bak", GetTime());
try {
boost::filesystem::rename(pathDatabase, pathDatabaseBak);
- printf("Moved old %s to %s. Retrying.\n", pathDatabase.string().c_str(), pathDatabaseBak.string().c_str());
+ LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string().c_str(), pathDatabaseBak.string().c_str());
} catch(boost::filesystem::filesystem_error &error) {
// failure is ok (well, not really, but it's not worse than what we started with)
}
@@ -702,12 +710,12 @@ bool AppInit2(boost::thread_group& threadGroup)
filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i-1);
try {
filesystem::create_hard_link(source, dest);
- printf("Hardlinked %s -> %s\n", source.string().c_str(), dest.string().c_str());
+ LogPrintf("Hardlinked %s -> %s\n", source.string().c_str(), dest.string().c_str());
linked = true;
} catch (filesystem::filesystem_error & e) {
// Note: hardlink creation failing is not a disaster, it just means
// blocks will get re-downloaded from peers.
- printf("Error hardlinking blk%04u.dat : %s\n", i, e.what());
+ LogPrintf("Error hardlinking blk%04u.dat : %s\n", i, e.what());
break;
}
}
@@ -758,7 +766,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around).
- if (!mapBlockIndex.empty() && pindexGenesisBlock == NULL)
+ if (!mapBlockIndex.empty() && chainActive.Genesis() == NULL)
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
// Initialize the block index (no-op if non-empty database was already loaded)
@@ -775,12 +783,12 @@ bool AppInit2(boost::thread_group& threadGroup)
uiInterface.InitMessage(_("Verifying blocks..."));
if (!VerifyDB(GetArg("-checklevel", 3),
- GetArg( "-checkblocks", 288))) {
+ GetArg("-checkblocks", 288))) {
strLoadError = _("Corrupted block database detected");
break;
}
} catch(std::exception &e) {
- if (fDebug) printf("%s\n", e.what());
+ if (fDebug) LogPrintf("%s\n", e.what());
strLoadError = _("Error opening block database");
break;
}
@@ -798,7 +806,7 @@ bool AppInit2(boost::thread_group& threadGroup)
fReindex = true;
fRequestShutdown = false;
} else {
- printf("Aborted block database rebuild. Exiting.\n");
+ LogPrintf("Aborted block database rebuild. Exiting.\n");
return false;
}
} else {
@@ -812,10 +820,10 @@ bool AppInit2(boost::thread_group& threadGroup)
// As the program has not fully started yet, Shutdown() is possibly overkill.
if (fRequestShutdown)
{
- printf("Shutdown requested. Exiting.\n");
+ LogPrintf("Shutdown requested. Exiting.\n");
return false;
}
- printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ LogPrintf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false))
{
@@ -837,12 +845,12 @@ bool AppInit2(boost::thread_group& threadGroup)
ReadBlockFromDisk(block, pindex);
block.BuildMerkleTree();
block.print();
- printf("\n");
+ LogPrintf("\n");
nFound++;
}
}
if (nFound == 0)
- printf("No blocks matching %s were found\n", strMatch.c_str());
+ LogPrintf("No blocks matching %s were found\n", strMatch.c_str());
return false;
}
@@ -869,7 +877,7 @@ bool AppInit2(boost::thread_group& threadGroup)
else if (nLoadWalletRet == DB_NEED_REWRITE)
{
strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n";
- printf("%s", strErrors.str().c_str());
+ LogPrintf("%s", strErrors.str().c_str());
return InitError(strErrors.str());
}
else
@@ -881,12 +889,12 @@ bool AppInit2(boost::thread_group& threadGroup)
int nMaxVersion = GetArg("-upgradewallet", 0);
if (nMaxVersion == 0) // the -upgradewallet without argument case
{
- printf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
+ LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
nMaxVersion = CLIENT_VERSION;
pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
}
else
- printf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < pwalletMain->GetVersion())
strErrors << _("Cannot downgrade wallet") << "\n";
pwalletMain->SetMaxVersion(nMaxVersion);
@@ -904,34 +912,34 @@ bool AppInit2(boost::thread_group& threadGroup)
strErrors << _("Cannot write default address") << "\n";
}
- pwalletMain->SetBestChain(CBlockLocator(pindexBest));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
}
- printf("%s", strErrors.str().c_str());
- printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ LogPrintf("%s", strErrors.str().c_str());
+ LogPrintf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
RegisterWallet(pwalletMain);
- CBlockIndex *pindexRescan = pindexBest;
+ CBlockIndex *pindexRescan = chainActive.Tip();
if (GetBoolArg("-rescan", false))
- pindexRescan = pindexGenesisBlock;
+ pindexRescan = chainActive.Genesis();
else
{
CWalletDB walletdb(strWalletFile);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
- pindexRescan = locator.GetBlockIndex();
+ pindexRescan = chainActive.FindFork(locator);
else
- pindexRescan = pindexGenesisBlock;
+ pindexRescan = chainActive.Genesis();
}
- if (pindexBest && pindexBest != pindexRescan)
+ if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
{
uiInterface.InitMessage(_("Rescanning..."));
- printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
+ LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
- printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
- pwalletMain->SetBestChain(CBlockLocator(pindexBest));
+ LogPrintf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ pwalletMain->SetBestChain(chainActive.GetLocator());
nWalletDBUpdated++;
}
@@ -959,10 +967,10 @@ bool AppInit2(boost::thread_group& threadGroup)
{
CAddrDB adb;
if (!adb.Read(addrman))
- printf("Invalid or missing peers.dat; recreating\n");
+ LogPrintf("Invalid or missing peers.dat; recreating\n");
}
- printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
+ LogPrintf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
addrman.size(), GetTimeMillis() - nStart);
// ********************************************************* Step 11: start node
@@ -976,11 +984,11 @@ bool AppInit2(boost::thread_group& threadGroup)
RandAddSeedPerfmon();
//// debug print
- printf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
- printf("nBestHeight = %d\n", nBestHeight);
- printf("setKeyPool.size() = %"PRIszu"\n", pwalletMain->setKeyPool.size());
- printf("mapWallet.size() = %"PRIszu"\n", pwalletMain->mapWallet.size());
- printf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain->mapAddressBook.size());
+ LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
+ LogPrintf("nBestHeight = %d\n", chainActive.Height());
+ LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
+ LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
+ LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
StartNode(threadGroup);
@@ -990,17 +998,20 @@ bool AppInit2(boost::thread_group& threadGroup)
StartRPCThreads();
// Generate coins in the background
- GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
+ if (pwalletMain)
+ GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
// ********************************************************* Step 12: finished
uiInterface.InitMessage(_("Done loading"));
- // Add wallet transactions that aren't already in a block to mapTransactions
- pwalletMain->ReacceptWalletTransactions();
+ if (pwalletMain) {
+ // Add wallet transactions that aren't already in a block to mapTransactions
+ pwalletMain->ReacceptWalletTransactions();
- // Run a thread to flush wallet periodically
- threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile)));
+ // Run a thread to flush wallet periodically
+ threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile)));
+ }
return !fRequestShutdown;
}
diff --git a/src/key.cpp b/src/key.cpp
index fe5222378a..414845a9da 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -202,17 +202,19 @@ public:
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
if (sig == NULL)
return false;
- if (BN_is_odd(sig->s)) {
- // enforce even S values, by negating the value (modulo the order) if odd
- BN_CTX *ctx = BN_CTX_new();
- BN_CTX_start(ctx);
- const EC_GROUP *group = EC_KEY_get0_group(pkey);
- BIGNUM *order = BN_CTX_get(ctx);
- EC_GROUP_get_order(group, order, ctx);
+ BN_CTX *ctx = BN_CTX_new();
+ BN_CTX_start(ctx);
+ const EC_GROUP *group = EC_KEY_get0_group(pkey);
+ BIGNUM *order = BN_CTX_get(ctx);
+ BIGNUM *halforder = BN_CTX_get(ctx);
+ EC_GROUP_get_order(group, order, ctx);
+ BN_rshift1(halforder, order);
+ if (BN_cmp(sig->s, halforder) > 0) {
+ // enforce low S values, by negating the value (modulo the order) if above order/2.
BN_sub(sig->s, order, sig->s);
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
}
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
unsigned int nSize = ECDSA_size(pkey);
vchSig.resize(nSize); // Make sure it is big enough
unsigned char *pos = &vchSig[0];
diff --git a/src/leveldb.cpp b/src/leveldb.cpp
index 5e3fa08f5e..fb202367c4 100644
--- a/src/leveldb.cpp
+++ b/src/leveldb.cpp
@@ -15,7 +15,7 @@
void HandleError(const leveldb::Status &status) throw(leveldb_error) {
if (status.ok())
return;
- printf("%s\n", status.ToString().c_str());
+ LogPrintf("%s\n", status.ToString().c_str());
if (status.IsCorruption())
throw leveldb_error("Database corrupted");
if (status.IsIOError())
@@ -48,15 +48,15 @@ CLevelDB::CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool
options.env = penv;
} else {
if (fWipe) {
- printf("Wiping LevelDB in %s\n", path.string().c_str());
+ LogPrintf("Wiping LevelDB in %s\n", path.string().c_str());
leveldb::DestroyDB(path.string(), options);
}
boost::filesystem::create_directory(path);
- printf("Opening LevelDB in %s\n", path.string().c_str());
+ LogPrintf("Opening LevelDB in %s\n", path.string().c_str());
}
leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
HandleError(status);
- printf("Opened LevelDB successfully\n");
+ LogPrintf("Opened LevelDB successfully\n");
}
CLevelDB::~CLevelDB() {
diff --git a/src/leveldb.h b/src/leveldb.h
index 79262edbb5..7daddeb493 100644
--- a/src/leveldb.h
+++ b/src/leveldb.h
@@ -5,6 +5,7 @@
#define BITCOIN_LEVELDB_H
#include "serialize.h"
+#include "util.h"
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
@@ -91,7 +92,7 @@ public:
if (!status.ok()) {
if (status.IsNotFound())
return false;
- printf("LevelDB read failure: %s\n", status.ToString().c_str());
+ LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str());
HandleError(status);
}
try {
@@ -120,7 +121,7 @@ public:
if (!status.ok()) {
if (status.IsNotFound())
return false;
- printf("LevelDB read failure: %s\n", status.ToString().c_str());
+ LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str());
HandleError(status);
}
return true;
diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile
index 96af7765be..20c9c4f287 100644
--- a/src/leveldb/Makefile
+++ b/src/leveldb/Makefile
@@ -31,6 +31,7 @@ TESTHARNESS = ./util/testharness.o $(TESTUTIL)
TESTS = \
arena_test \
+ autocompact_test \
bloom_test \
c_test \
cache_test \
@@ -70,7 +71,7 @@ SHARED = $(SHARED1)
else
# Update db.h if you change these.
SHARED_MAJOR = 1
-SHARED_MINOR = 12
+SHARED_MINOR = 13
SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT)
SHARED2 = $(SHARED1).$(SHARED_MAJOR)
SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR)
@@ -114,6 +115,9 @@ leveldbutil: db/leveldb_main.o $(LIBOBJECTS)
arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
+autocompact_test: db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS)
+ $(CXX) $(LDFLAGS) db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
+
bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
diff --git a/src/leveldb/db/autocompact_test.cc b/src/leveldb/db/autocompact_test.cc
new file mode 100644
index 0000000000..d20a2362c3
--- /dev/null
+++ b/src/leveldb/db/autocompact_test.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2013 The LevelDB Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file. See the AUTHORS file for names of contributors.
+
+#include "leveldb/db.h"
+#include "db/db_impl.h"
+#include "leveldb/cache.h"
+#include "util/testharness.h"
+#include "util/testutil.h"
+
+namespace leveldb {
+
+class AutoCompactTest {
+ public:
+ std::string dbname_;
+ Cache* tiny_cache_;
+ Options options_;
+ DB* db_;
+
+ AutoCompactTest() {
+ dbname_ = test::TmpDir() + "/autocompact_test";
+ tiny_cache_ = NewLRUCache(100);
+ options_.block_cache = tiny_cache_;
+ DestroyDB(dbname_, options_);
+ options_.create_if_missing = true;
+ options_.compression = kNoCompression;
+ ASSERT_OK(DB::Open(options_, dbname_, &db_));
+ }
+
+ ~AutoCompactTest() {
+ delete db_;
+ DestroyDB(dbname_, Options());
+ delete tiny_cache_;
+ }
+
+ std::string Key(int i) {
+ char buf[100];
+ snprintf(buf, sizeof(buf), "key%06d", i);
+ return std::string(buf);
+ }
+
+ uint64_t Size(const Slice& start, const Slice& limit) {
+ Range r(start, limit);
+ uint64_t size;
+ db_->GetApproximateSizes(&r, 1, &size);
+ return size;
+ }
+
+ void DoReads(int n);
+};
+
+static const int kValueSize = 200 * 1024;
+static const int kTotalSize = 100 * 1024 * 1024;
+static const int kCount = kTotalSize / kValueSize;
+
+// Read through the first n keys repeatedly and check that they get
+// compacted (verified by checking the size of the key space).
+void AutoCompactTest::DoReads(int n) {
+ std::string value(kValueSize, 'x');
+ DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
+
+ // Fill database
+ for (int i = 0; i < kCount; i++) {
+ ASSERT_OK(db_->Put(WriteOptions(), Key(i), value));
+ }
+ ASSERT_OK(dbi->TEST_CompactMemTable());
+
+ // Delete everything
+ for (int i = 0; i < kCount; i++) {
+ ASSERT_OK(db_->Delete(WriteOptions(), Key(i)));
+ }
+ ASSERT_OK(dbi->TEST_CompactMemTable());
+
+ // Get initial measurement of the space we will be reading.
+ const int64_t initial_size = Size(Key(0), Key(n));
+ const int64_t initial_other_size = Size(Key(n), Key(kCount));
+
+ // Read until size drops significantly.
+ std::string limit_key = Key(n);
+ for (int read = 0; true; read++) {
+ ASSERT_LT(read, 100) << "Taking too long to compact";
+ Iterator* iter = db_->NewIterator(ReadOptions());
+ for (iter->SeekToFirst();
+ iter->Valid() && iter->key().ToString() < limit_key;
+ iter->Next()) {
+ // Drop data
+ }
+ delete iter;
+ // Wait a little bit to allow any triggered compactions to complete.
+ Env::Default()->SleepForMicroseconds(1000000);
+ uint64_t size = Size(Key(0), Key(n));
+ fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n",
+ read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0);
+ if (size <= initial_size/10) {
+ break;
+ }
+ }
+
+ // Verify that the size of the key space not touched by the reads
+ // is pretty much unchanged.
+ const int64_t final_other_size = Size(Key(n), Key(kCount));
+ ASSERT_LE(final_other_size, initial_other_size + 1048576);
+ ASSERT_GE(final_other_size, initial_other_size/5 - 1048576);
+}
+
+TEST(AutoCompactTest, ReadAll) {
+ DoReads(kCount);
+}
+
+TEST(AutoCompactTest, ReadHalf) {
+ DoReads(kCount/2);
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) {
+ return leveldb::test::RunAllTests();
+}
diff --git a/src/leveldb/db/corruption_test.cc b/src/leveldb/db/corruption_test.cc
index 31b2d5f416..b37ffdfe64 100644
--- a/src/leveldb/db/corruption_test.cc
+++ b/src/leveldb/db/corruption_test.cc
@@ -35,6 +35,7 @@ class CorruptionTest {
CorruptionTest() {
tiny_cache_ = NewLRUCache(100);
options_.env = &env_;
+ options_.block_cache = tiny_cache_;
dbname_ = test::TmpDir() + "/db_test";
DestroyDB(dbname_, options_);
@@ -50,17 +51,14 @@ class CorruptionTest {
delete tiny_cache_;
}
- Status TryReopen(Options* options = NULL) {
+ Status TryReopen() {
delete db_;
db_ = NULL;
- Options opt = (options ? *options : options_);
- opt.env = &env_;
- opt.block_cache = tiny_cache_;
- return DB::Open(opt, dbname_, &db_);
+ return DB::Open(options_, dbname_, &db_);
}
- void Reopen(Options* options = NULL) {
- ASSERT_OK(TryReopen(options));
+ void Reopen() {
+ ASSERT_OK(TryReopen());
}
void RepairDB() {
@@ -92,6 +90,10 @@ class CorruptionTest {
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
uint64_t key;
Slice in(iter->key());
+ if (in == "" || in == "~") {
+ // Ignore boundary keys.
+ continue;
+ }
if (!ConsumeDecimalNumber(&in, &key) ||
!in.empty() ||
key < next_expected) {
@@ -233,7 +235,7 @@ TEST(CorruptionTest, TableFile) {
dbi->TEST_CompactRange(1, NULL, NULL);
Corrupt(kTableFile, 100, 1);
- Check(99, 99);
+ Check(90, 99);
}
TEST(CorruptionTest, TableFileIndexData) {
@@ -299,7 +301,7 @@ TEST(CorruptionTest, CompactionInputError) {
ASSERT_EQ(1, Property("leveldb.num-files-at-level" + NumberToString(last)));
Corrupt(kTableFile, 100, 1);
- Check(9, 9);
+ Check(5, 9);
// Force compactions by writing lots of values
Build(10000);
@@ -307,32 +309,23 @@ TEST(CorruptionTest, CompactionInputError) {
}
TEST(CorruptionTest, CompactionInputErrorParanoid) {
- Options options;
- options.paranoid_checks = true;
- options.write_buffer_size = 1048576;
- Reopen(&options);
+ options_.paranoid_checks = true;
+ options_.write_buffer_size = 512 << 10;
+ Reopen();
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
- // Fill levels >= 1 so memtable compaction outputs to level 1
- for (int level = 1; level < config::kNumLevels; level++) {
- dbi->Put(WriteOptions(), "", "begin");
- dbi->Put(WriteOptions(), "~", "end");
+ // Make multiple inputs so we need to compact.
+ for (int i = 0; i < 2; i++) {
+ Build(10);
dbi->TEST_CompactMemTable();
+ Corrupt(kTableFile, 100, 1);
+ env_.SleepForMicroseconds(100000);
}
+ dbi->CompactRange(NULL, NULL);
- Build(10);
- dbi->TEST_CompactMemTable();
- ASSERT_EQ(1, Property("leveldb.num-files-at-level0"));
-
- Corrupt(kTableFile, 100, 1);
- Check(9, 9);
-
- // Write must eventually fail because of corrupted table
- Status s;
+ // Write must fail because of corrupted table
std::string tmp1, tmp2;
- for (int i = 0; i < 10000 && s.ok(); i++) {
- s = db_->Put(WriteOptions(), Key(i, &tmp1), Value(i, &tmp2));
- }
+ Status s = db_->Put(WriteOptions(), Key(5, &tmp1), Value(5, &tmp2));
ASSERT_TRUE(!s.ok()) << "write did not fail in corrupted paranoid db";
}
diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc
index 395d3172ad..fa1351038b 100644
--- a/src/leveldb/db/db_impl.cc
+++ b/src/leveldb/db/db_impl.cc
@@ -113,14 +113,14 @@ Options SanitizeOptions(const std::string& dbname,
return result;
}
-DBImpl::DBImpl(const Options& options, const std::string& dbname)
- : env_(options.env),
- internal_comparator_(options.comparator),
- internal_filter_policy_(options.filter_policy),
- options_(SanitizeOptions(
- dbname, &internal_comparator_, &internal_filter_policy_, options)),
- owns_info_log_(options_.info_log != options.info_log),
- owns_cache_(options_.block_cache != options.block_cache),
+DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
+ : env_(raw_options.env),
+ internal_comparator_(raw_options.comparator),
+ internal_filter_policy_(raw_options.filter_policy),
+ options_(SanitizeOptions(dbname, &internal_comparator_,
+ &internal_filter_policy_, raw_options)),
+ owns_info_log_(options_.info_log != raw_options.info_log),
+ owns_cache_(options_.block_cache != raw_options.block_cache),
dbname_(dbname),
db_lock_(NULL),
shutting_down_(NULL),
@@ -130,6 +130,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
logfile_(NULL),
logfile_number_(0),
log_(NULL),
+ seed_(0),
tmp_batch_(new WriteBatch),
bg_compaction_scheduled_(false),
manual_compaction_(NULL),
@@ -138,7 +139,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
has_imm_.Release_Store(NULL);
// Reserve ten files or so for other uses and give the rest to TableCache.
- const int table_cache_size = options.max_open_files - kNumNonTableCacheFiles;
+ const int table_cache_size = options_.max_open_files - kNumNonTableCacheFiles;
table_cache_ = new TableCache(dbname_, &options_, table_cache_size);
versions_ = new VersionSet(dbname_, &options_, table_cache_,
@@ -1027,7 +1028,8 @@ static void CleanupIteratorState(void* arg1, void* arg2) {
} // namespace
Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
- SequenceNumber* latest_snapshot) {
+ SequenceNumber* latest_snapshot,
+ uint32_t* seed) {
IterState* cleanup = new IterState;
mutex_.Lock();
*latest_snapshot = versions_->LastSequence();
@@ -1051,13 +1053,15 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
cleanup->version = versions_->current();
internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, NULL);
+ *seed = ++seed_;
mutex_.Unlock();
return internal_iter;
}
Iterator* DBImpl::TEST_NewInternalIterator() {
SequenceNumber ignored;
- return NewInternalIterator(ReadOptions(), &ignored);
+ uint32_t ignored_seed;
+ return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed);
}
int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() {
@@ -1114,12 +1118,21 @@ Status DBImpl::Get(const ReadOptions& options,
Iterator* DBImpl::NewIterator(const ReadOptions& options) {
SequenceNumber latest_snapshot;
- Iterator* internal_iter = NewInternalIterator(options, &latest_snapshot);
+ uint32_t seed;
+ Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed);
return NewDBIterator(
- &dbname_, env_, user_comparator(), internal_iter,
+ this, user_comparator(), iter,
(options.snapshot != NULL
? reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_
- : latest_snapshot));
+ : latest_snapshot),
+ seed);
+}
+
+void DBImpl::RecordReadSample(Slice key) {
+ MutexLock l(&mutex_);
+ if (versions_->current()->RecordReadSample(key)) {
+ MaybeScheduleCompaction();
+ }
}
const Snapshot* DBImpl::GetSnapshot() {
diff --git a/src/leveldb/db/db_impl.h b/src/leveldb/db/db_impl.h
index 3c8d711ae0..75fd30abe9 100644
--- a/src/leveldb/db/db_impl.h
+++ b/src/leveldb/db/db_impl.h
@@ -59,13 +59,19 @@ class DBImpl : public DB {
// file at a level >= 1.
int64_t TEST_MaxNextLevelOverlappingBytes();
+ // Record a sample of bytes read at the specified internal key.
+ // Samples are taken approximately once every config::kReadBytesPeriod
+ // bytes.
+ void RecordReadSample(Slice key);
+
private:
friend class DB;
struct CompactionState;
struct Writer;
Iterator* NewInternalIterator(const ReadOptions&,
- SequenceNumber* latest_snapshot);
+ SequenceNumber* latest_snapshot,
+ uint32_t* seed);
Status NewDB();
@@ -135,6 +141,7 @@ class DBImpl : public DB {
WritableFile* logfile_;
uint64_t logfile_number_;
log::Writer* log_;
+ uint32_t seed_; // For sampling.
// Queue of writers.
std::deque<Writer*> writers_;
diff --git a/src/leveldb/db/db_iter.cc b/src/leveldb/db/db_iter.cc
index 87dca2ded4..071a54e3f4 100644
--- a/src/leveldb/db/db_iter.cc
+++ b/src/leveldb/db/db_iter.cc
@@ -5,12 +5,14 @@
#include "db/db_iter.h"
#include "db/filename.h"
+#include "db/db_impl.h"
#include "db/dbformat.h"
#include "leveldb/env.h"
#include "leveldb/iterator.h"
#include "port/port.h"
#include "util/logging.h"
#include "util/mutexlock.h"
+#include "util/random.h"
namespace leveldb {
@@ -46,15 +48,16 @@ class DBIter: public Iterator {
kReverse
};
- DBIter(const std::string* dbname, Env* env,
- const Comparator* cmp, Iterator* iter, SequenceNumber s)
- : dbname_(dbname),
- env_(env),
+ DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
+ uint32_t seed)
+ : db_(db),
user_comparator_(cmp),
iter_(iter),
sequence_(s),
direction_(kForward),
- valid_(false) {
+ valid_(false),
+ rnd_(seed),
+ bytes_counter_(RandomPeriod()) {
}
virtual ~DBIter() {
delete iter_;
@@ -100,8 +103,12 @@ class DBIter: public Iterator {
}
}
- const std::string* const dbname_;
- Env* const env_;
+ // Pick next gap with average value of config::kReadBytesPeriod.
+ ssize_t RandomPeriod() {
+ return rnd_.Uniform(2*config::kReadBytesPeriod);
+ }
+
+ DBImpl* db_;
const Comparator* const user_comparator_;
Iterator* const iter_;
SequenceNumber const sequence_;
@@ -112,13 +119,23 @@ class DBIter: public Iterator {
Direction direction_;
bool valid_;
+ Random rnd_;
+ ssize_t bytes_counter_;
+
// No copying allowed
DBIter(const DBIter&);
void operator=(const DBIter&);
};
inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
- if (!ParseInternalKey(iter_->key(), ikey)) {
+ Slice k = iter_->key();
+ ssize_t n = k.size() + iter_->value().size();
+ bytes_counter_ -= n;
+ while (bytes_counter_ < 0) {
+ bytes_counter_ += RandomPeriod();
+ db_->RecordReadSample(k);
+ }
+ if (!ParseInternalKey(k, ikey)) {
status_ = Status::Corruption("corrupted internal key in DBIter");
return false;
} else {
@@ -288,12 +305,12 @@ void DBIter::SeekToLast() {
} // anonymous namespace
Iterator* NewDBIterator(
- const std::string* dbname,
- Env* env,
+ DBImpl* db,
const Comparator* user_key_comparator,
Iterator* internal_iter,
- const SequenceNumber& sequence) {
- return new DBIter(dbname, env, user_key_comparator, internal_iter, sequence);
+ SequenceNumber sequence,
+ uint32_t seed) {
+ return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
}
} // namespace leveldb
diff --git a/src/leveldb/db/db_iter.h b/src/leveldb/db/db_iter.h
index d9e1b174ab..04927e937b 100644
--- a/src/leveldb/db/db_iter.h
+++ b/src/leveldb/db/db_iter.h
@@ -11,15 +11,17 @@
namespace leveldb {
+class DBImpl;
+
// Return a new iterator that converts internal keys (yielded by
// "*internal_iter") that were live at the specified "sequence" number
// into appropriate user keys.
extern Iterator* NewDBIterator(
- const std::string* dbname,
- Env* env,
+ DBImpl* db,
const Comparator* user_key_comparator,
Iterator* internal_iter,
- const SequenceNumber& sequence);
+ SequenceNumber sequence,
+ uint32_t seed);
} // namespace leveldb
diff --git a/src/leveldb/db/dbformat.h b/src/leveldb/db/dbformat.h
index f7f64dafb6..5d8a032bd3 100644
--- a/src/leveldb/db/dbformat.h
+++ b/src/leveldb/db/dbformat.h
@@ -38,6 +38,9 @@ static const int kL0_StopWritesTrigger = 12;
// space if the same key space is being repeatedly overwritten.
static const int kMaxMemCompactLevel = 2;
+// Approximate gap in bytes between samples of data read during iteration.
+static const int kReadBytesPeriod = 1048576;
+
} // namespace config
class InternalKey;
diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc
index 4fd1ddef21..66d73be71f 100644
--- a/src/leveldb/db/version_set.cc
+++ b/src/leveldb/db/version_set.cc
@@ -289,6 +289,51 @@ static bool NewestFirst(FileMetaData* a, FileMetaData* b) {
return a->number > b->number;
}
+void Version::ForEachOverlapping(Slice user_key, Slice internal_key,
+ void* arg,
+ bool (*func)(void*, int, FileMetaData*)) {
+ // TODO(sanjay): Change Version::Get() to use this function.
+ const Comparator* ucmp = vset_->icmp_.user_comparator();
+
+ // Search level-0 in order from newest to oldest.
+ std::vector<FileMetaData*> tmp;
+ tmp.reserve(files_[0].size());
+ for (uint32_t i = 0; i < files_[0].size(); i++) {
+ FileMetaData* f = files_[0][i];
+ if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
+ ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
+ tmp.push_back(f);
+ }
+ }
+ if (!tmp.empty()) {
+ std::sort(tmp.begin(), tmp.end(), NewestFirst);
+ for (uint32_t i = 0; i < tmp.size(); i++) {
+ if (!(*func)(arg, 0, tmp[i])) {
+ return;
+ }
+ }
+ }
+
+ // Search other levels.
+ for (int level = 1; level < config::kNumLevels; level++) {
+ size_t num_files = files_[level].size();
+ if (num_files == 0) continue;
+
+ // Binary search to find earliest index whose largest key >= internal_key.
+ uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key);
+ if (index < num_files) {
+ FileMetaData* f = files_[level][index];
+ if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) {
+ // All of "f" is past any data for user_key
+ } else {
+ if (!(*func)(arg, level, f)) {
+ return;
+ }
+ }
+ }
+ }
+}
+
Status Version::Get(const ReadOptions& options,
const LookupKey& k,
std::string* value,
@@ -401,6 +446,44 @@ bool Version::UpdateStats(const GetStats& stats) {
return false;
}
+bool Version::RecordReadSample(Slice internal_key) {
+ ParsedInternalKey ikey;
+ if (!ParseInternalKey(internal_key, &ikey)) {
+ return false;
+ }
+
+ struct State {
+ GetStats stats; // Holds first matching file
+ int matches;
+
+ static bool Match(void* arg, int level, FileMetaData* f) {
+ State* state = reinterpret_cast<State*>(arg);
+ state->matches++;
+ if (state->matches == 1) {
+ // Remember first match.
+ state->stats.seek_file = f;
+ state->stats.seek_file_level = level;
+ }
+ // We can stop iterating once we have a second match.
+ return state->matches < 2;
+ }
+ };
+
+ State state;
+ state.matches = 0;
+ ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match);
+
+ // Must have at least two matches since we want to merge across
+ // files. But what if we have a single file that contains many
+ // overwrites and deletions? Should we have another mechanism for
+ // finding such files?
+ if (state.matches >= 2) {
+ // 1MB cost is about 1 seek (see comment in Builder::Apply).
+ return UpdateStats(state.stats);
+ }
+ return false;
+}
+
void Version::Ref() {
++refs_;
}
@@ -435,10 +518,13 @@ int Version::PickLevelForMemTableOutput(
if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) {
break;
}
- GetOverlappingInputs(level + 2, &start, &limit, &overlaps);
- const int64_t sum = TotalFileSize(overlaps);
- if (sum > kMaxGrandParentOverlapBytes) {
- break;
+ if (level + 2 < config::kNumLevels) {
+ // Check that file does not overlap too many grandparent bytes.
+ GetOverlappingInputs(level + 2, &start, &limit, &overlaps);
+ const int64_t sum = TotalFileSize(overlaps);
+ if (sum > kMaxGrandParentOverlapBytes) {
+ break;
+ }
}
level++;
}
@@ -452,6 +538,8 @@ void Version::GetOverlappingInputs(
const InternalKey* begin,
const InternalKey* end,
std::vector<FileMetaData*>* inputs) {
+ assert(level >= 0);
+ assert(level < config::kNumLevels);
inputs->clear();
Slice user_begin, user_end;
if (begin != NULL) {
diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h
index 9d084fdb7d..20de0e2629 100644
--- a/src/leveldb/db/version_set.h
+++ b/src/leveldb/db/version_set.h
@@ -78,6 +78,12 @@ class Version {
// REQUIRES: lock is held
bool UpdateStats(const GetStats& stats);
+ // Record a sample of bytes read at the specified internal key.
+ // Samples are taken approximately once every config::kReadBytesPeriod
+ // bytes. Returns true if a new compaction may need to be triggered.
+ // REQUIRES: lock is held
+ bool RecordReadSample(Slice key);
+
// Reference count management (so Versions do not disappear out from
// under live iterators)
void Ref();
@@ -114,6 +120,15 @@ class Version {
class LevelFileNumIterator;
Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const;
+ // Call func(arg, level, f) for every file that overlaps user_key in
+ // order from newest to oldest. If an invocation of func returns
+ // false, makes no more calls.
+ //
+ // REQUIRES: user portion of internal_key == user_key.
+ void ForEachOverlapping(Slice user_key, Slice internal_key,
+ void* arg,
+ bool (*func)(void*, int, FileMetaData*));
+
VersionSet* vset_; // VersionSet to which this Version belongs
Version* next_; // Next version in linked list
Version* prev_; // Previous version in linked list
diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h
index da8b11a8c0..57c00a5da0 100644
--- a/src/leveldb/include/leveldb/db.h
+++ b/src/leveldb/include/leveldb/db.h
@@ -14,7 +14,7 @@ namespace leveldb {
// Update Makefile if you change these
static const int kMajorVersion = 1;
-static const int kMinorVersion = 12;
+static const int kMinorVersion = 13;
struct Options;
struct ReadOptions;
diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
index 6badfdc230..0f5dcfac5a 100644
--- a/src/leveldb/util/env_posix.cc
+++ b/src/leveldb/util/env_posix.cc
@@ -320,8 +320,39 @@ class PosixMmapFile : public WritableFile {
return Status::OK();
}
- virtual Status Sync() {
+ Status SyncDirIfManifest() {
+ const char* f = filename_.c_str();
+ const char* sep = strrchr(f, '/');
+ Slice basename;
+ std::string dir;
+ if (sep == NULL) {
+ dir = ".";
+ basename = f;
+ } else {
+ dir = std::string(f, sep - f);
+ basename = sep + 1;
+ }
Status s;
+ if (basename.starts_with("MANIFEST")) {
+ int fd = open(dir.c_str(), O_RDONLY);
+ if (fd < 0) {
+ s = IOError(dir, errno);
+ } else {
+ if (fsync(fd) < 0) {
+ s = IOError(dir, errno);
+ }
+ close(fd);
+ }
+ }
+ return s;
+ }
+
+ virtual Status Sync() {
+ // Ensure new files referred to by the manifest are in the filesystem.
+ Status s = SyncDirIfManifest();
+ if (!s.ok()) {
+ return s;
+ }
if (pending_sync_) {
// Some unmapped data was not synced
diff --git a/src/leveldb/util/random.h b/src/leveldb/util/random.h
index 07538242ea..ddd51b1c7b 100644
--- a/src/leveldb/util/random.h
+++ b/src/leveldb/util/random.h
@@ -16,7 +16,12 @@ class Random {
private:
uint32_t seed_;
public:
- explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { }
+ explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
+ // Avoid bad seeds.
+ if (seed_ == 0 || seed_ == 2147483647L) {
+ seed_ = 1;
+ }
+ }
uint32_t Next() {
static const uint32_t M = 2147483647L; // 2^31-1
static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0
diff --git a/src/m4/ax_boost_base.m4 b/src/m4/ax_boost_base.m4
new file mode 100644
index 0000000000..54a2a1bee7
--- /dev/null
+++ b/src/m4/ax_boost_base.m4
@@ -0,0 +1,258 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# Test for the Boost C++ libraries of a particular version (or newer)
+#
+# If no path to the installed boost library is given the macro searchs
+# under /usr, /usr/local, /opt and /opt/local and evaluates the
+# $BOOST_ROOT environment variable. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
+#
+# And sets:
+#
+# HAVE_BOOST
+#
+# LICENSE
+#
+# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2009 Peter Adolphs
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 20
+
+AC_DEFUN([AX_BOOST_BASE],
+[
+AC_ARG_WITH([boost],
+ [AS_HELP_STRING([--with-boost@<:@=ARG@:>@],
+ [use Boost library from a standard location (ARG=yes),
+ from the specified location (ARG=<path>),
+ or disable it (ARG=no)
+ @<:@ARG=yes@:>@ ])],
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ac_boost_path=""
+ else
+ want_boost="yes"
+ ac_boost_path="$withval"
+ fi
+ ],
+ [want_boost="yes"])
+
+
+AC_ARG_WITH([boost-libdir],
+ AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
+ [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
+ [
+ if test -d "$withval"
+ then
+ ac_boost_lib_path="$withval"
+ else
+ AC_MSG_ERROR(--with-boost-libdir expected directory name)
+ fi
+ ],
+ [ac_boost_lib_path=""]
+)
+
+if test "x$want_boost" = "xyes"; then
+ boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
+ boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
+ boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
+ boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
+ boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+ if test "x$boost_lib_version_req_sub_minor" = "x" ; then
+ boost_lib_version_req_sub_minor="0"
+ fi
+ WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
+ AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
+ succeeded=no
+
+ dnl On 64-bit systems check for system libraries in both lib64 and lib.
+ dnl The former is specified by FHS, but e.g. Debian does not adhere to
+ dnl this (as it rises problems for generic multi-arch support).
+ dnl The last entry in the list is chosen by default when no libraries
+ dnl are found, e.g. when only header-only libraries are installed!
+ libsubdirs="lib"
+ ax_arch=`uname -m`
+ if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = s390x -o $ax_arch = sparc64; then
+ libsubdirs="lib64 lib lib64"
+ fi
+
+ dnl first we check the system location for boost libraries
+ dnl this location ist chosen if boost libraries are installed with the --layout=system option
+ dnl or if you install boost with RPM
+ if test "$ac_boost_path" != ""; then
+ BOOST_CPPFLAGS="-I$ac_boost_path/include"
+ for ac_boost_path_tmp in $libsubdirs; do
+ if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then
+ BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
+ break
+ fi
+ done
+ elif test "$cross_compiling" != yes; then
+ for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
+ if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
+ BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
+ break;
+ fi
+ done
+ fi
+
+ dnl overwrite ld flags if we have required special directory with
+ dnl --with-boost-libdir parameter
+ if test "$ac_boost_lib_path" != ""; then
+ BOOST_LDFLAGS="-L$ac_boost_lib_path"
+ fi
+
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <boost/version.hpp>
+ ]], [[
+ #if BOOST_VERSION >= $WANT_BOOST_VERSION
+ // Everything is okay
+ #else
+ # error Boost version is too old
+ #endif
+ ]])],[
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+ found_system=yes
+ ],[
+ ])
+ AC_LANG_POP([C++])
+
+
+
+ dnl if we found no boost with system layout we search for boost libraries
+ dnl built and installed without the --layout=system option or for a staged(not installed) version
+ if test "x$succeeded" != "xyes"; then
+ _version=0
+ if test "$ac_boost_path" != ""; then
+ if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
+ for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
+ _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+ V_CHECK=`expr $_version_tmp \> $_version`
+ if test "$V_CHECK" = "1" ; then
+ _version=$_version_tmp
+ fi
+ VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
+ BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
+ done
+ fi
+ else
+ if test "$cross_compiling" != yes; then
+ for ac_boost_path in /usr /usr/local /opt /opt/local ; do
+ if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
+ for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
+ _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+ V_CHECK=`expr $_version_tmp \> $_version`
+ if test "$V_CHECK" = "1" ; then
+ _version=$_version_tmp
+ best_path=$ac_boost_path
+ fi
+ done
+ fi
+ done
+
+ VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
+ BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
+ if test "$ac_boost_lib_path" = ""; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ BOOST_LDFLAGS="-L$best_path/$libsubdir"
+ fi
+ fi
+
+ if test "x$BOOST_ROOT" != "x"; then
+ for libsubdir in $libsubdirs ; do
+ if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
+ done
+ if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then
+ version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
+ stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
+ stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
+ V_CHECK=`expr $stage_version_shorten \>\= $_version`
+ if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
+ AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
+ BOOST_CPPFLAGS="-I$BOOST_ROOT"
+ BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
+ fi
+ fi
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <boost/version.hpp>
+ ]], [[
+ #if BOOST_VERSION >= $WANT_BOOST_VERSION
+ // Everything is okay
+ #else
+ # error Boost version is too old
+ #endif
+ ]])],[
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+ found_system=yes
+ ],[
+ ])
+ AC_LANG_POP([C++])
+ fi
+
+ if test "$succeeded" != "yes" ; then
+ if test "$_version" = "0" ; then
+ AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
+ else
+ AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
+ fi
+ # execute ACTION-IF-NOT-FOUND (if present):
+ ifelse([$3], , :, [$3])
+ else
+ AC_SUBST(BOOST_CPPFLAGS)
+ AC_SUBST(BOOST_LDFLAGS)
+ AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
+ # execute ACTION-IF-FOUND (if present):
+ ifelse([$2], , :, [$2])
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+fi
+
+])
diff --git a/src/m4/ax_boost_chrono.m4 b/src/m4/ax_boost_chrono.m4
new file mode 100644
index 0000000000..9b3958ec74
--- /dev/null
+++ b/src/m4/ax_boost_chrono.m4
@@ -0,0 +1,118 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_CHRONO
+#
+# DESCRIPTION
+#
+# Test for System library from the Boost C++ libraries. The macro requires
+# a preceding call to AX_BOOST_BASE. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_CHRONO_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_CHRONO
+#
+# LICENSE
+#
+# Copyright (c) 2012 Xiyue Deng <manphiz@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 1
+
+AC_DEFUN([AX_BOOST_CHRONO],
+[
+ AC_ARG_WITH([boost-chrono],
+ AS_HELP_STRING([--with-boost-chrono@<:@=special-lib@:>@],
+ [use the Chrono library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-chrono=boost_chrono-gcc-mt ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_chrono_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_chrono_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_BUILD])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::Chrono library is available,
+ ax_cv_boost_chrono,
+ [AC_LANG_PUSH([C++])
+ CXXFLAGS_SAVE=$CXXFLAGS
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/chrono.hpp>]],
+ [[boost::chrono::system_clock::time_point time;]])],
+ ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no)
+ CXXFLAGS=$CXXFLAGS_SAVE
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_chrono" = "xyes"; then
+ AC_SUBST(BOOST_CPPFLAGS)
+
+ AC_DEFINE(HAVE_BOOST_CHRONO,,[define if the Boost::Chrono library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+ LDFLAGS_SAVE=$LDFLAGS
+ if test "x$ax_boost_user_chrono_lib" = "x"; then
+ for libextension in `ls $BOOSTLIBDIR/libboost_chrono*.so* $BOOSTLIBDIR/libboost_chrono*.dylib* $BOOSTLIBDIR/libboost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_chrono.*\)\.so.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.a.*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
+ [link_chrono="no"])
+ done
+ if test "x$link_chrono" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_chrono*.dll* $BOOSTLIBDIR/boost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_chrono.*\)\.dll.*$;\1;' -e 's;^\(boost_chrono.*\)\.a.*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
+ [link_chrono="no"])
+ done
+ fi
+
+ else
+ for ax_lib in $ax_boost_user_chrono_lib boost_chrono-$ax_boost_user_chrono_lib; do
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
+ [link_chrono="no"])
+ done
+
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_chrono" = "xno"; then
+ AC_MSG_ERROR(Could not link against $ax_lib !)
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/src/m4/ax_boost_filesystem.m4 b/src/m4/ax_boost_filesystem.m4
new file mode 100644
index 0000000000..2a62da8d89
--- /dev/null
+++ b/src/m4/ax_boost_filesystem.m4
@@ -0,0 +1,118 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_FILESYSTEM
+#
+# DESCRIPTION
+#
+# Test for Filesystem library from the Boost C++ libraries. The macro
+# requires a preceding call to AX_BOOST_BASE. Further documentation is
+# available at <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_FILESYSTEM_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_FILESYSTEM
+#
+# LICENSE
+#
+# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2009 Michael Tindal
+# Copyright (c) 2009 Roman Rybalko <libtorrent@romanr.info>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 21
+
+AC_DEFUN([AX_BOOST_FILESYSTEM],
+[
+ AC_ARG_WITH([boost-filesystem],
+ AS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@],
+ [use the Filesystem library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_filesystem_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_filesystem_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ LIBS_SAVED=$LIBS
+ LIBS="$LIBS $BOOST_SYSTEM_LIB"
+ export LIBS
+
+ AC_CACHE_CHECK(whether the Boost::Filesystem library is available,
+ ax_cv_boost_filesystem,
+ [AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/filesystem/path.hpp>]],
+ [[using namespace boost::filesystem;
+ path my_path( "foo/bar/data.txt" );
+ return 0;]])],
+ ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no)
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_filesystem" = "xyes"; then
+ AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ if test "x$ax_boost_user_filesystem_lib" = "x"; then
+ for libextension in `ls $BOOSTLIBDIR/libboost_filesystem*.so* $BOOSTLIBDIR/libboost_filesystem*.dylib* $BOOSTLIBDIR/libboost_filesystem*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_filesystem.*\)\.so.*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.a*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.dylib$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break],
+ [link_filesystem="no"])
+ done
+ if test "x$link_program_options" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_filesystem*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_filesystem.*\)\.dll.*$;\1;' -e 's;^\(boost_filesystem.*\)\.a*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break],
+ [link_filesystem="no"])
+ done
+ fi
+ else
+ for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break],
+ [link_filesystem="no"])
+ done
+
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_filesystem" != "xyes"; then
+ AC_MSG_ERROR(Could not link against $ax_lib !)
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ LIBS="$LIBS_SAVED"
+ fi
+])
diff --git a/src/m4/ax_boost_program_options.m4 b/src/m4/ax_boost_program_options.m4
new file mode 100644
index 0000000000..d612f91da3
--- /dev/null
+++ b/src/m4/ax_boost_program_options.m4
@@ -0,0 +1,108 @@
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_program_options.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_PROGRAM_OPTIONS
+#
+# DESCRIPTION
+#
+# Test for program options library from the Boost C++ libraries. The macro
+# requires a preceding call to AX_BOOST_BASE. Further documentation is
+# available at <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_PROGRAM_OPTIONS
+#
+# LICENSE
+#
+# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 20
+
+AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS],
+[
+ AC_ARG_WITH([boost-program-options],
+ AS_HELP_STRING([--with-boost-program-options@<:@=special-lib@:>@],
+ [use the program options library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-program-options=boost_program_options-gcc-mt-1_33_1 ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_program_options_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_program_options_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ export want_boost
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+ AC_CACHE_CHECK([whether the Boost::Program_Options library is available],
+ ax_cv_boost_program_options,
+ [AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/program_options.hpp>
+ ]],
+ [[boost::program_options::options_description generic("Generic options");
+ return 0;]])],
+ ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no)
+ AC_LANG_POP([C++])
+ ])
+ if test "$ax_cv_boost_program_options" = yes; then
+ AC_DEFINE(HAVE_BOOST_PROGRAM_OPTIONS,,[define if the Boost::PROGRAM_OPTIONS library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ if test "x$ax_boost_user_program_options_lib" = "x"; then
+ for libextension in `ls $BOOSTLIBDIR/libboost_program_options*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.a*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break],
+ [link_program_options="no"])
+ done
+ if test "x$link_program_options" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_program_options*.dll* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.dll.*$;\1;'` `ls $BOOSTLIBDIR/boost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.a*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break],
+ [link_program_options="no"])
+ done
+ fi
+ else
+ for ax_lib in $ax_boost_user_program_options_lib boost_program_options-$ax_boost_user_program_options_lib; do
+ AC_CHECK_LIB($ax_lib, main,
+ [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break],
+ [link_program_options="no"])
+ done
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_program_options" != "xyes"; then
+ AC_MSG_ERROR([Could not link against [$ax_lib] !])
+ fi
+ fi
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/src/m4/ax_boost_system.m4 b/src/m4/ax_boost_system.m4
new file mode 100644
index 0000000000..7fbf6d360d
--- /dev/null
+++ b/src/m4/ax_boost_system.m4
@@ -0,0 +1,120 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_system.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_SYSTEM
+#
+# DESCRIPTION
+#
+# Test for System library from the Boost C++ libraries. The macro requires
+# a preceding call to AX_BOOST_BASE. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_SYSTEM_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_SYSTEM
+#
+# LICENSE
+#
+# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2008 Michael Tindal
+# Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 14
+
+AC_DEFUN([AX_BOOST_SYSTEM],
+[
+ AC_ARG_WITH([boost-system],
+ AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@],
+ [use the System library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-system=boost_system-gcc-mt ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_system_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_system_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_BUILD])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::System library is available,
+ ax_cv_boost_system,
+ [AC_LANG_PUSH([C++])
+ CXXFLAGS_SAVE=$CXXFLAGS
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
+ [[boost::system::system_category]])],
+ ax_cv_boost_system=yes, ax_cv_boost_system=no)
+ CXXFLAGS=$CXXFLAGS_SAVE
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_system" = "xyes"; then
+ AC_SUBST(BOOST_CPPFLAGS)
+
+ AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+ LDFLAGS_SAVE=$LDFLAGS
+ if test "x$ax_boost_user_system_lib" = "x"; then
+ for libextension in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.a*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
+ [link_system="no"])
+ done
+ if test "x$link_system" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_system*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_system.*\)\.dll.*$;\1;' -e 's;^\(boost_system.*\)\.a*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
+ [link_system="no"])
+ done
+ fi
+
+ else
+ for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
+ [link_system="no"])
+ done
+
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_system" = "xno"; then
+ AC_MSG_ERROR(Could not link against $ax_lib !)
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/src/m4/ax_boost_thread.m4 b/src/m4/ax_boost_thread.m4
new file mode 100644
index 0000000000..d9cd8a1d1d
--- /dev/null
+++ b/src/m4/ax_boost_thread.m4
@@ -0,0 +1,153 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_THREAD
+#
+# DESCRIPTION
+#
+# Test for Thread library from the Boost C++ libraries. The macro requires
+# a preceding call to AX_BOOST_BASE. Further documentation is available at
+# <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_THREAD_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_THREAD
+#
+# LICENSE
+#
+# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
+# Copyright (c) 2009 Michael Tindal
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 22
+
+AC_DEFUN([AX_BOOST_THREAD],
+[
+ AC_ARG_WITH([boost-thread],
+ AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],
+ [use the Thread library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-thread=boost_thread-gcc-mt ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_thread_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_thread_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_BUILD])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::Thread library is available,
+ ax_cv_boost_thread,
+ [AC_LANG_PUSH([C++])
+ CXXFLAGS_SAVE=$CXXFLAGS
+
+ # let us handle platform dependent issues in
+ # configure.ac
+
+ # if test "x$build_os" = "xsolaris" ; then
+ # CXXFLAGS="-pthreads $CXXFLAGS"
+ # elif test "x$build_os" = "xming32" ; then
+ # CXXFLAGS="-mthreads $CXXFLAGS"
+ # else
+ # CXXFLAGS="-pthread $CXXFLAGS"
+ # fi
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]],
+ [[boost::thread_group thrds;
+ return 0;]])],
+ ax_cv_boost_thread=yes, ax_cv_boost_thread=no)
+ CXXFLAGS=$CXXFLAGS_SAVE
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_thread" = "xyes"; then
+ # if test "x$build_os" = "xsolaris" ; then
+ # BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS"
+ # elif test "x$build_os" = "xming32" ; then
+ # BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS"
+ # else
+ # BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS"
+ # fi
+
+ AC_SUBST(BOOST_CPPFLAGS)
+
+ AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+ LDFLAGS_SAVE=$LDFLAGS
+ # case "x$build_os" in
+ # *bsd* )
+ # LDFLAGS="-pthread $LDFLAGS"
+ # break;
+ # ;;
+ # esac
+ if test "x$ax_boost_user_thread_lib" = "x"; then
+ for libextension in `ls $BOOSTLIBDIR/libboost_thread*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_thread.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_thread*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_thread.*\)\.a*$;\1;'`; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
+ [link_thread="no"])
+ done
+ if test "x$link_thread" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_thread*.dll* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_thread.*\)\.dll.*$;\1;'` `ls $BOOSTLIBDIR/boost_thread*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_thread.*\)\.a*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
+ [link_thread="no"])
+ done
+ fi
+
+ else
+ for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
+ [link_thread="no"])
+ done
+
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ # if test "x$link_thread" = "xno"; then
+ # AC_MSG_ERROR(Could not link against $ax_lib !)
+ # else
+ # case "x$build_os" in
+ # *bsd* )
+ # BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS"
+ # break;
+ # ;;
+ # esac
+
+ # fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/src/m4/ax_boost_unit_test_framework.m4 b/src/m4/ax_boost_unit_test_framework.m4
new file mode 100644
index 0000000000..1115f55121
--- /dev/null
+++ b/src/m4/ax_boost_unit_test_framework.m4
@@ -0,0 +1,137 @@
+# ================================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html
+# ================================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_UNIT_TEST_FRAMEWORK
+#
+# DESCRIPTION
+#
+# Test for Unit_Test_Framework library from the Boost C++ libraries. The
+# macro requires a preceding call to AX_BOOST_BASE. Further documentation
+# is available at <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_UNIT_TEST_FRAMEWORK
+#
+# LICENSE
+#
+# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 19
+
+AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK],
+[
+ AC_ARG_WITH([boost-unit-test-framework],
+ AS_HELP_STRING([--with-boost-unit-test-framework@<:@=special-lib@:>@],
+ [use the Unit_Test_Framework library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-unit-test-framework=boost_unit_test_framework-gcc ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_unit_test_framework_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_unit_test_framework_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+
+ AC_CACHE_CHECK(whether the Boost::Unit_Test_Framework library is available,
+ ax_cv_boost_unit_test_framework,
+ [AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/test/unit_test.hpp>]],
+ [[using boost::unit_test::test_suite;
+ test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); return 0;]])],
+ ax_cv_boost_unit_test_framework=yes, ax_cv_boost_unit_test_framework=no)
+ AC_LANG_POP([C++])
+ ])
+ if test "x$ax_cv_boost_unit_test_framework" = "xyes"; then
+ AC_DEFINE(HAVE_BOOST_UNIT_TEST_FRAMEWORK,,[define if the Boost::Unit_Test_Framework library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+
+ if test "x$ax_boost_user_unit_test_framework_lib" = "x"; then
+ saved_ldflags="${LDFLAGS}"
+ for monitor_library in `ls $BOOSTLIBDIR/libboost_unit_test_framework*.so* $BOOSTLIBDIR/libboost_unit_test_framework*.dylib* $BOOSTLIBDIR/libboost_unit_test_framework*.a* 2>/dev/null` ; do
+ if test -r $monitor_library ; then
+ libextension=`echo $monitor_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a.*$;\1;'`
+ ax_lib=${libextension}
+ link_unit_test_framework="yes"
+ else
+ link_unit_test_framework="no"
+ fi
+
+ if test "x$link_unit_test_framework" = "xyes"; then
+ BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib"
+ AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB)
+ break
+ fi
+ done
+ if test "x$link_unit_test_framework" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_unit_test_framework*.dll* $BOOSTLIBDIR/boost_unit_test_framework*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_unit_test_framework.*\)\.dll.*$;\1;' -e 's;^\(boost_unit_test_framework.*\)\.a.*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib"; AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) link_unit_test_framework="yes"; break],
+ [link_unit_test_framework="no"])
+ done
+ fi
+ else
+ link_unit_test_framework="no"
+ saved_ldflags="${LDFLAGS}"
+ for ax_lib in boost_unit_test_framework-$ax_boost_user_unit_test_framework_lib $ax_boost_user_unit_test_framework_lib ; do
+ if test "x$link_unit_test_framework" = "xyes"; then
+ break;
+ fi
+ for unittest_library in `ls $BOOSTLIBDIR/lib${ax_lib}.so* $BOOSTLIBDIR/lib${ax_lib}.a* 2>/dev/null` ; do
+ if test -r $unittest_library ; then
+ libextension=`echo $unittest_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a*$;\1;'`
+ ax_lib=${libextension}
+ link_unit_test_framework="yes"
+ else
+ link_unit_test_framework="no"
+ fi
+
+ if test "x$link_unit_test_framework" = "xyes"; then
+ BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib"
+ AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB)
+ break
+ fi
+ done
+ done
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_unit_test_framework" != "xyes"; then
+ AC_MSG_ERROR(Could not link against $ax_lib !)
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])
diff --git a/src/m4/ax_check_compile_flag.m4 b/src/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000000..c3a8d695a1
--- /dev/null
+++ b/src/m4/ax_check_compile_flag.m4
@@ -0,0 +1,72 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 2
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/src/m4/ax_check_link_flag.m4 b/src/m4/ax_check_link_flag.m4
new file mode 100644
index 0000000000..e2d0d363e4
--- /dev/null
+++ b/src/m4/ax_check_link_flag.m4
@@ -0,0 +1,71 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the linker or gives an error.
+# (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the linker's default flags
+# when the check is done. The check is thus made with the flags: "LDFLAGS
+# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
+# issue an error when a bad flag is given.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 2
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $4 $1"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM()],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ LDFLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
diff --git a/src/m4/ax_check_preproc_flag.m4 b/src/m4/ax_check_preproc_flag.m4
new file mode 100644
index 0000000000..b1cfef6b86
--- /dev/null
+++ b/src/m4/ax_check_preproc_flag.m4
@@ -0,0 +1,72 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's
+# preprocessor or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the preprocessor's default
+# flags when the check is done. The check is thus made with the flags:
+# "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the
+# preprocessor to issue an error when a bad flag is given.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 2
+
+AC_DEFUN([AX_CHECK_PREPROC_FLAG],
+[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [
+ ax_check_save_flags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $4 $1"
+ AC_PREPROC_IFELSE([AC_LANG_PROGRAM()],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ CPPFLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_PREPROC_FLAGS
diff --git a/src/m4/ax_pthread.m4 b/src/m4/ax_pthread.m4
new file mode 100644
index 0000000000..6d400ed4e8
--- /dev/null
+++ b/src/m4/ax_pthread.m4
@@ -0,0 +1,317 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC to any special C compiler that is needed for
+# multi-threaded programs (defaults to the value of CC otherwise). (This
+# is necessary on AIX to use the special cc_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also link it with them as well. e.g. you should link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threads programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
+# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 20
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test x"$ax_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case ${host_os} in
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+ ;;
+
+ darwin*)
+ ax_pthread_flags="-pthread $ax_pthread_flags"
+ ;;
+esac
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
+ if test x"$ax_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test "x$ax_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+ [int attr = $attr; return attr /* ; */])],
+ [attr_name=$attr; break],
+ [])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case ${host_os} in
+ aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+ osf* | hpux*) flag="-D_REENTRANT";;
+ solaris*)
+ if test "$GCC" = "yes"; then
+ flag="-D_REENTRANT"
+ else
+ flag="-mt -D_REENTRANT"
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ ax_cv_PTHREAD_PRIO_INHERIT, [
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+ AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: compile with *_r variant
+ if test "x$GCC" != xyes; then
+ case $host_os in
+ aix*)
+ AS_CASE(["x/$CC"],
+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+ [#handle absolute path differently from PATH based program lookup
+ AS_CASE(["x$CC"],
+ [x/*],
+ [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+ [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+ ;;
+ esac
+ fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/src/m4/bitcoin_find_bdb48.m4 b/src/m4/bitcoin_find_bdb48.m4
new file mode 100644
index 0000000000..72ec49b635
--- /dev/null
+++ b/src/m4/bitcoin_find_bdb48.m4
@@ -0,0 +1,66 @@
+AC_DEFUN([BITCOIN_FIND_BDB48],[
+ AC_MSG_CHECKING([for Berkeley DB C++ headers])
+ BDB_CPPFLAGS=
+ BDB_LIBS=
+ bdbpath=X
+ bdb48path=X
+ bdbdirlist=
+ for _vn in 4.8 48 4 5 ''; do
+ for _pfx in b lib ''; do
+ bdbdirlist="$bdbdirlist ${_pfx}db${_vn}"
+ done
+ done
+ for searchpath in $bdbdirlist ''; do
+ test -n "${searchpath}" && searchpath="${searchpath}/"
+ AC_TRY_COMPILE([
+ #include <${searchpath}db_cxx.h>
+ ],[
+ #if !((DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 8) || DB_VERSION_MAJOR > 4)
+ #error "failed to find bdb 4.8+"
+ #endif
+ ],[
+ if test "x$bdbpath" = "xX"; then
+ bdbpath="${searchpath}"
+ fi
+ ],[
+ continue
+ ])
+ AC_TRY_COMPILE([
+ #include <${searchpath}db_cxx.h>
+ ],[
+ #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 8)
+ #error "failed to find bdb 4.8"
+ #endif
+ ],[
+ bdb48path="${searchpath}"
+ break
+ ])
+ done
+ if test "x$bdbpath" = "xX"; then
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR(libdb_cxx headers missing)
+ elif test "x$bdb48path" = "xX"; then
+ BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdbpath}],db_cxx)
+ AC_ARG_WITH([incompatible-bdb],[AS_HELP_STRING([--with-incompatible-bdb], [allow using a bdb version other than 4.8])],[
+ AC_MSG_WARN([Found Berkeley DB other than 4.8; wallets opened by this build will not be portable!])
+ ],[
+ AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore)])
+ ])
+ else
+ BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdb48path}],db_cxx)
+ bdbpath="${bdb48path}"
+ fi
+ AC_SUBST(BDB_CPPFLAGS)
+
+ # TODO: Ideally this could find the library version and make sure it matches the headers being used
+ for searchlib in db_cxx-4.8 db_cxx; do
+ AC_CHECK_LIB([$searchlib],[main],[
+ BDB_LIBS="-l${searchlib}"
+ break
+ ])
+ done
+ if test "x$BDB_LIBS" = "x"; then
+ AC_MSG_ERROR(libdb_cxx missing)
+ fi
+ AC_SUBST(BDB_LIBS)
+])
diff --git a/src/m4/bitcoin_subdir_to_include.m4 b/src/m4/bitcoin_subdir_to_include.m4
new file mode 100644
index 0000000000..66f106c7d4
--- /dev/null
+++ b/src/m4/bitcoin_subdir_to_include.m4
@@ -0,0 +1,14 @@
+dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE])
+dnl SUBDIRECTORY-NAME must end with a path separator
+AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[
+ if test "x$2" = "x"; then
+ AC_MSG_RESULT([default])
+ else
+ echo "#include <$2$3.h>" >conftest.cpp
+ newinclpath=`${CXXCPP} ${CPPFLAGS} -M conftest.cpp 2>/dev/null | [ tr -d '\\n\\r\\\\' | sed -e 's/^.*[[:space:]:]\(\/[^[:space:]]*\)]$3[\.h[[:space:]].*$/\1/' -e t -e d`]
+ AC_MSG_RESULT([${newinclpath}])
+ if test "x${newinclpath}" != "x"; then
+ eval "$1=\"\$$1\"' -I${newinclpath}'"
+ fi
+ fi
+])
diff --git a/src/main.cpp b/src/main.cpp
index 24fd1fadbc..215a7ba620 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -32,13 +32,8 @@ CTxMemPool mempool;
unsigned int nTransactionsUpdated = 0;
map<uint256, CBlockIndex*> mapBlockIndex;
-std::vector<CBlockIndex*> vBlockIndexByHeight;
-CBlockIndex* pindexGenesisBlock = NULL;
-int nBestHeight = -1;
-uint256 nBestChainWork = 0;
+CChain chainActive;
uint256 nBestInvalidWork = 0;
-uint256 hashBestChain = 0;
-CBlockIndex* pindexBest = NULL;
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
int64 nTimeBestReceived = 0;
int nScriptCheckThreads = 0;
@@ -67,9 +62,6 @@ CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n";
-double dHashesPerSec = 0.0;
-int64 nHPSTimerStart = 0;
-
// Settings
int64 nTransactionFee = 0;
@@ -176,106 +168,83 @@ void static ResendWalletTransactions()
// Registration of network node signals.
//
+int static GetHeight()
+{
+ LOCK(cs_main);
+ return chainActive.Height();
+}
+
void RegisterNodeSignals(CNodeSignals& nodeSignals)
{
+ nodeSignals.GetHeight.connect(&GetHeight);
nodeSignals.ProcessMessages.connect(&ProcessMessages);
nodeSignals.SendMessages.connect(&SendMessages);
}
void UnregisterNodeSignals(CNodeSignals& nodeSignals)
{
+ nodeSignals.GetHeight.disconnect(&GetHeight);
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
nodeSignals.SendMessages.disconnect(&SendMessages);
}
//////////////////////////////////////////////////////////////////////////////
//
-// CBlockLocator implementation
+// CChain implementation
//
-CBlockLocator::CBlockLocator(uint256 hashBlock)
-{
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- Set((*mi).second);
+CBlockIndex *CChain::SetTip(CBlockIndex *pindex) {
+ if (pindex == NULL) {
+ vChain.clear();
+ return NULL;
+ }
+ vChain.resize(pindex->nHeight + 1);
+ while (pindex && vChain[pindex->nHeight] != pindex) {
+ vChain[pindex->nHeight] = pindex;
+ pindex = pindex->pprev;
+ }
+ return pindex;
}
-void CBlockLocator::Set(const CBlockIndex* pindex)
-{
- vHave.clear();
+CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
int nStep = 1;
- while (pindex)
- {
- vHave.push_back(pindex->GetBlockHash());
+ std::vector<uint256> vHave;
+ vHave.reserve(32);
- // Exponentially larger steps back
- for (int i = 0; pindex && i < nStep; i++)
+ if (!pindex)
+ pindex = Tip();
+ while (pindex) {
+ vHave.push_back(pindex->GetBlockHash());
+ // Stop when we have added the genesis block.
+ if (pindex->nHeight == 0)
+ break;
+ // Exponentially larger steps back, plus the genesis block.
+ int nHeight = std::max(pindex->nHeight - nStep, 0);
+ // In case pindex is not in this chain, iterate pindex->pprev to find blocks.
+ while (pindex->nHeight > nHeight && !Contains(pindex))
pindex = pindex->pprev;
+ // If pindex is in this chain, use direct height-based access.
+ if (pindex->nHeight > nHeight)
+ pindex = (*this)[nHeight];
if (vHave.size() > 10)
nStep *= 2;
}
- vHave.push_back(Params().HashGenesisBlock());
-}
-int CBlockLocator::GetDistanceBack()
-{
- // Retrace how far back it was in the sender's branch
- int nDistance = 0;
- int nStep = 1;
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return nDistance;
- }
- nDistance += nStep;
- if (nDistance > 10)
- nStep *= 2;
- }
- return nDistance;
+ return CBlockLocator(vHave);
}
-CBlockIndex *CBlockLocator::GetBlockIndex()
-{
+CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
// Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
+ BOOST_FOREACH(const uint256& hash, locator.vHave) {
std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
+ if (Contains(pindex))
return pindex;
}
}
- return pindexGenesisBlock;
-}
-
-uint256 CBlockLocator::GetBlockHash()
-{
- // Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return hash;
- }
- }
- return Params().HashGenesisBlock();
-}
-
-int CBlockLocator::GetHeight()
-{
- CBlockIndex* pindex = GetBlockIndex();
- if (!pindex)
- return 0;
- return pindex->nHeight;
+ return Genesis();
}
//////////////////////////////////////////////////////////////////////////////
@@ -415,7 +384,7 @@ bool AddOrphanTx(const CTransaction& tx)
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz > 5000)
{
- printf("ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString().c_str());
+ LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString().c_str());
return false;
}
@@ -423,7 +392,7 @@ bool AddOrphanTx(const CTransaction& tx)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
- printf("stored orphan tx %s (mapsz %"PRIszu")\n", hash.ToString().c_str(),
+ LogPrint("mempool", "stored orphan tx %s (mapsz %"PRIszu")\n", hash.ToString().c_str(),
mapOrphanTransactions.size());
return true;
}
@@ -466,7 +435,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
bool IsStandardTx(const CTransaction& tx, string& reason)
{
- if (tx.nVersion > CTransaction::CURRENT_VERSION) {
+ if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
reason = "version";
return false;
}
@@ -520,7 +489,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64 nBlockTime)
if (tx.nLockTime == 0)
return true;
if (nBlockHeight == 0)
- nBlockHeight = nBestHeight;
+ nBlockHeight = chainActive.Height();
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
if ((int64)tx.nLockTime < ((int64)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
@@ -647,7 +616,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
if (pblock == NULL) {
CCoins coins;
if (pcoinsTip->GetCoins(GetHash(), coins)) {
- CBlockIndex *pindex = FindBlockByHeight(coins.nHeight);
+ CBlockIndex *pindex = chainActive[coins.nHeight];
if (pindex) {
if (!ReadBlockFromDisk(blockTmp, pindex))
return 0;
@@ -668,7 +637,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
{
vMerkleBranch.clear();
nIndex = -1;
- printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
+ LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
return 0;
}
@@ -681,10 +650,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
- if (!pindex || !pindex->IsInMainChain())
+ if (!pindex || !chainActive.Contains(pindex))
return 0;
- return pindexBest->nHeight - pindex->nHeight + 1;
+ return chainActive.Height() - pindex->nHeight + 1;
}
@@ -787,7 +756,7 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
}
bool CTxMemPool::accept(CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs)
+ bool* pfMissingInputs, bool fRejectInsaneFee)
{
if (pfMissingInputs)
*pfMissingInputs = false;
@@ -917,10 +886,15 @@ bool CTxMemPool::accept(CValidationState &state, const CTransaction &tx, bool fL
if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
return error("CTxMemPool::accept() : free transaction rejected by rate limiter");
if (fDebug)
- printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
+ LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize;
}
+ if (fRejectInsaneFee && nFees > CTransaction::nMinRelayTxFee * 10000)
+ return error("CTxMemPool::accept() : insane fees %s, %"PRI64d" > %"PRI64d,
+ hash.ToString().c_str(),
+ nFees, CTransaction::nMinRelayTxFee * 10000);
+
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
@@ -934,7 +908,7 @@ bool CTxMemPool::accept(CValidationState &state, const CTransaction &tx, bool fL
LOCK(cs);
if (ptxOld)
{
- printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
+ LogPrint("mempool", "CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
remove(*ptxOld);
}
addUnchecked(hash, tx);
@@ -946,7 +920,7 @@ bool CTxMemPool::accept(CValidationState &state, const CTransaction &tx, bool fL
EraseFromWallets(ptxOld->GetHash());
SyncWithWallets(hash, tx, NULL, true);
- printf("CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
+ LogPrint("mempool", "CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
hash.ToString().c_str(),
mapTx.size());
return true;
@@ -1021,7 +995,7 @@ void CTxMemPool::check(CCoinsViewCache *pcoins) const
if (!fChecks)
return;
- printf("Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
+ LogPrintf("Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
LOCK(cs);
for (std::map<uint256, CTransaction>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
@@ -1076,7 +1050,7 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
- if (!pindex || !pindex->IsInMainChain())
+ if (!pindex || !chainActive.Contains(pindex))
return 0;
// Make sure the merkle branch connects to this block
@@ -1088,7 +1062,7 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
}
pindexRet = pindex;
- return pindexBest->nHeight - pindex->nHeight + 1;
+ return chainActive.Height() - pindex->nHeight + 1;
}
@@ -1096,7 +1070,7 @@ int CMerkleTx::GetBlocksToMaturity() const
{
if (!IsCoinBase())
return 0;
- return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
+ return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
}
@@ -1171,7 +1145,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
nHeight = coins.nHeight;
}
if (nHeight > 0)
- pindexSlow = FindBlockByHeight(nHeight);
+ pindexSlow = chainActive[nHeight];
}
}
@@ -1201,14 +1175,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex
//
-static CBlockIndex* pblockindexFBBHLast;
-CBlockIndex* FindBlockByHeight(int nHeight)
-{
- if (nHeight >= (int)vBlockIndexByHeight.size())
- return NULL;
- return vBlockIndexByHeight[nHeight];
-}
-
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
{
// Open history file to append
@@ -1354,7 +1320,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
// Limit adjustment step
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
- printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
+ LogPrintf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
if (nActualTimespan < nTargetTimespan/4)
nActualTimespan = nTargetTimespan/4;
if (nActualTimespan > nTargetTimespan*4)
@@ -1370,10 +1336,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
bnNew = Params().ProofOfWorkLimit();
/// debug print
- printf("GetNextWorkRequired RETARGET\n");
- printf("nTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"\n", nTargetTimespan, nActualTimespan);
- printf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str());
- printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
+ LogPrintf("GetNextWorkRequired RETARGET\n");
+ LogPrintf("nTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"\n", nTargetTimespan, nActualTimespan);
+ LogPrintf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString().c_str());
+ LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
return bnNew.GetCompact();
}
@@ -1402,17 +1368,17 @@ int GetNumBlocksOfPeers()
bool IsInitialBlockDownload()
{
- if (pindexBest == NULL || fImporting || fReindex || nBestHeight < Checkpoints::GetTotalBlocksEstimate())
+ if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
return true;
static int64 nLastUpdate;
static CBlockIndex* pindexLastBest;
- if (pindexBest != pindexLastBest)
+ if (chainActive.Tip() != pindexLastBest)
{
- pindexLastBest = pindexBest;
+ pindexLastBest = chainActive.Tip();
nLastUpdate = GetTime();
}
return (GetTime() - nLastUpdate < 10 &&
- pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
+ chainActive.Tip()->GetBlockTime() < GetTime() - 24 * 60 * 60);
}
bool fLargeWorkForkFound = false;
@@ -1421,12 +1387,17 @@ CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
void CheckForkWarningConditions()
{
+ // Before we get past initial download, we cannot reliably alert about forks
+ // (we assume we don't get stuck on a fork before the last checkpoint)
+ if (IsInitialBlockDownload())
+ return;
+
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
// of our head, drop it
- if (pindexBestForkTip && nBestHeight - pindexBestForkTip->nHeight >= 72)
+ if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72)
pindexBestForkTip = NULL;
- if (pindexBestForkTip || nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
+ if (pindexBestForkTip || nBestInvalidWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6).getuint256())
{
if (!fLargeWorkForkFound)
{
@@ -1441,14 +1412,14 @@ void CheckForkWarningConditions()
}
if (pindexBestForkTip)
{
- printf("CheckForkWarningConditions: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n",
+ LogPrintf("CheckForkWarningConditions: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n",
pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString().c_str(),
pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString().c_str());
fLargeWorkForkFound = true;
}
else
{
- printf("CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n");
+ LogPrintf("CheckForkWarningConditions: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n");
fLargeWorkInvalidChainFound = true;
}
}
@@ -1463,7 +1434,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
{
// If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex* pfork = pindexNewForkTip;
- CBlockIndex* plonger = pindexBest;
+ CBlockIndex* plonger = chainActive.Tip();
while (pfork && pfork != plonger)
{
while (plonger && plonger->nHeight > pfork->nHeight)
@@ -1482,7 +1453,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7).getuint256() &&
- nBestHeight - pindexNewForkTip->nHeight < 72)
+ chainActive.Height() - pindexNewForkTip->nHeight < 72)
{
pindexBestForkTip = pindexNewForkTip;
pindexBestForkBase = pfork;
@@ -1499,13 +1470,13 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
pblocktree->WriteBestInvalidWork(CBigNum(nBestInvalidWork));
uiInterface.NotifyBlocksChanged();
}
- printf("InvalidChainFound: invalid block=%s height=%d log2_work=%.8g date=%s\n",
+ LogPrintf("InvalidChainFound: invalid block=%s height=%d log2_work=%.8g date=%s\n",
pindexNew->GetBlockHash().ToString().c_str(), pindexNew->nHeight,
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
pindexNew->GetBlockTime()).c_str());
- printf("InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s\n",
- hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0),
- DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
+ LogPrintf("InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s\n",
+ chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0),
+ DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str());
CheckForkWarningConditions();
}
@@ -1514,7 +1485,7 @@ void static InvalidBlockFound(CBlockIndex *pindex) {
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
setBlockIndexValid.erase(pindex);
InvalidChainFound(pindex);
- if (pindex->GetNextInMainChain()) {
+ if (chainActive.Next(pindex)) {
CValidationState stateDummy;
ConnectBestBlock(stateDummy); // reorganise away from the failed block
}
@@ -1531,7 +1502,7 @@ bool ConnectBestBlock(CValidationState &state) {
pindexNewBest = *it;
}
- if (pindexNewBest == pindexBest || (pindexBest && pindexNewBest->nChainWork == pindexBest->nChainWork))
+ if (pindexNewBest == chainActive.Tip() || (chainActive.Tip() && pindexNewBest->nChainWork == chainActive.Tip()->nChainWork))
return true; // nothing to do
// check ancestry
@@ -1551,10 +1522,10 @@ bool ConnectBestBlock(CValidationState &state) {
break;
}
- if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
+ if (chainActive.Tip() == NULL || pindexTest->nChainWork > chainActive.Tip()->nChainWork)
vAttach.push_back(pindexTest);
- if (pindexTest->pprev == NULL || pindexTest->GetNextInMainChain()) {
+ if (pindexTest->pprev == NULL || chainActive.Next(pindexTest)) {
reverse(vAttach.begin(), vAttach.end());
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
boost::this_thread::interruption_point();
@@ -1771,8 +1742,14 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
view.SetCoins(hash, CCoins());
}
CCoins &outs = view.GetCoins(hash);
+ outs.ClearUnspendable();
CCoins outsBlock = CCoins(tx, pindex->nHeight);
+ // The CCoins serialization does not serialize negative numbers.
+ // No network rules currently depend on the version here, so an inconsistency is harmless
+ // but it must be corrected before txout nversion ever influences a network rule.
+ if (outsBlock.nVersion < 0)
+ outs.nVersion = outsBlock.nVersion;
if (outs != outsBlock)
fClean = fClean && error("DisconnectBlock() : added transaction mismatch? database corrupted");
@@ -1868,7 +1845,6 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
// (its coinbase is unspendable)
if (block.GetHash() == Params().HashGenesisBlock()) {
view.SetBestBlock(pindex);
- pindexGenesisBlock = pindex;
return true;
}
@@ -1957,7 +1933,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
}
int64 nTime = GetTimeMicros() - nStart;
if (fBenchmark)
- printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)block.vtx.size(), 0.001 * nTime, 0.001 * nTime / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
+ LogPrintf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)block.vtx.size(), 0.001 * nTime, 0.001 * nTime / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
if (GetValueOut(block.vtx[0]) > GetBlockValue(pindex->nHeight, nFees))
return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(block.vtx[0]), GetBlockValue(pindex->nHeight, nFees)));
@@ -1966,7 +1942,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return state.DoS(100, false);
int64 nTime2 = GetTimeMicros() - nStart;
if (fBenchmark)
- printf("- Verify %u txins: %.2fms (%.3fms/txin)\n", nInputs - 1, 0.001 * nTime2, nInputs <= 1 ? 0 : 0.001 * nTime2 / (nInputs-1));
+ LogPrintf("- Verify %u txins: %.2fms (%.3fms/txin)\n", nInputs - 1, 0.001 * nTime2, nInputs <= 1 ? 0 : 0.001 * nTime2 / (nInputs-1));
if (fJustCheck)
return true;
@@ -2042,8 +2018,8 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
reverse(vConnect.begin(), vConnect.end());
if (vDisconnect.size() > 0) {
- printf("REORGANIZE: Disconnect %"PRIszu" blocks; %s..\n", vDisconnect.size(), pfork->GetBlockHash().ToString().c_str());
- printf("REORGANIZE: Connect %"PRIszu" blocks; ..%s\n", vConnect.size(), pindexNew->GetBlockHash().ToString().c_str());
+ LogPrintf("REORGANIZE: Disconnect %"PRIszu" blocks; %s...\n", vDisconnect.size(), pfork->GetBlockHash().ToString().c_str());
+ LogPrintf("REORGANIZE: Connect %"PRIszu" blocks; ...%s\n", vConnect.size(), pindexNew->GetBlockHash().ToString().c_str());
}
// Disconnect shorter branch
@@ -2056,7 +2032,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
if (!DisconnectBlock(block, state, pindex, view))
return error("SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str());
if (fBenchmark)
- printf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
+ LogPrintf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
// Queue memory transactions to resurrect.
// We only do this for blocks after the last checkpoint (reorganisation before that
@@ -2081,7 +2057,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
return error("SetBestBlock() : ConnectBlock %s failed", pindex->GetBlockHash().ToString().c_str());
}
if (fBenchmark)
- printf("- Connect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
+ LogPrintf("- Connect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
// Queue memory transactions to delete
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@@ -2094,7 +2070,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
assert(view.Flush());
int64 nTime = GetTimeMicros() - nStart;
if (fBenchmark)
- printf("- Flush %i transactions: %.2fms (%.4fms/tx)\n", nModified, 0.001 * nTime, 0.001 * nTime / nModified);
+ LogPrintf("- Flush %i transactions: %.2fms (%.4fms/tx)\n", nModified, 0.001 * nTime, 0.001 * nTime / nModified);
// Make sure it's successfully written to disk before changing memory structure
bool fIsInitialDownload = IsInitialBlockDownload();
@@ -2116,9 +2092,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Proceed by updating the memory structures.
// Register new best chain
- vBlockIndexByHeight.resize(pindexNew->nHeight + 1);
- BOOST_FOREACH(CBlockIndex* pindex, vConnect)
- vBlockIndexByHeight[pindex->nHeight] = pindex;
+ chainActive.SetTip(pindexNew);
// Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH(CTransaction& tx, vResurrect) {
@@ -2138,29 +2112,21 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Update best block in wallet (so we can detect restored wallets)
if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
- {
- const CBlockLocator locator(pindexNew);
- ::SetBestChain(locator);
- }
+ ::SetBestChain(chainActive.GetLocator(pindexNew));
// New best block
- hashBestChain = pindexNew->GetBlockHash();
- pindexBest = pindexNew;
- pblockindexFBBHLast = NULL;
- nBestHeight = pindexBest->nHeight;
- nBestChainWork = pindexNew->nChainWork;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
- printf("SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
- hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
- DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str(),
- Checkpoints::GuessVerificationProgress(pindexBest));
+ LogPrintf("SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
+ chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
+ DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str(),
+ Checkpoints::GuessVerificationProgress(chainActive.Tip()));
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
{
int nUpgraded = 0;
- const CBlockIndex* pindex = pindexBest;
+ const CBlockIndex* pindex = chainActive.Tip();
for (int i = 0; i < 100 && pindex != NULL; i++)
{
if (pindex->nVersion > CBlock::CURRENT_VERSION)
@@ -2168,7 +2134,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
pindex = pindex->pprev;
}
if (nUpgraded > 0)
- printf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, CBlock::CURRENT_VERSION);
+ LogPrintf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, CBlock::CURRENT_VERSION);
if (nUpgraded > 100/2)
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
@@ -2178,7 +2144,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
if (!fIsInitialDownload && !strCmd.empty())
{
- boost::replace_all(strCmd, "%s", hashBestChain.GetHex());
+ boost::replace_all(strCmd, "%s", chainActive.Tip()->GetBlockHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
}
@@ -2220,7 +2186,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
if (!ConnectBestBlock(state))
return false;
- if (pindexNew == pindexBest)
+ if (pindexNew == chainActive.Tip())
{
// Clear fork warning if its no longer applicable
CheckForkWarningConditions();
@@ -2254,7 +2220,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
}
} else {
while (infoLastBlockFile.nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
- printf("Leaving block file %i: %s\n", nLastBlockFile, infoLastBlockFile.ToString().c_str());
+ LogPrintf("Leaving block file %i: %s\n", nLastBlockFile, infoLastBlockFile.ToString().c_str());
FlushBlockFile(true);
nLastBlockFile++;
infoLastBlockFile.SetNull();
@@ -2275,7 +2241,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) {
FILE *file = OpenBlockFile(pos);
if (file) {
- printf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
+ LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos);
fclose(file);
}
@@ -2321,7 +2287,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) {
FILE *file = OpenUndoFile(pos);
if (file) {
- printf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
+ LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
AllocateFileRange(file, pos.nPos, nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos);
fclose(file);
}
@@ -2469,11 +2435,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
// Relay inventory, but don't relay old inventory during initial block download
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
- if (hashBestChain == hash)
+ if (chainActive.Tip()->GetBlockHash() == hash)
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
- if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
+ if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
pnode->PushInventory(CInv(MSG_BLOCK, hash));
}
@@ -2492,6 +2458,18 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
return (nFound >= nRequired);
}
+int64 CBlockIndex::GetMedianTime() const
+{
+ const CBlockIndex* pindex = this;
+ for (int i = 0; i < nMedianTimeSpan/2; i++)
+ {
+ if (!chainActive.Next(pindex))
+ return GetBlockTime();
+ pindex = chainActive.Next(pindex);
+ }
+ return pindex->GetMedianTimePast();
+}
+
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
{
// Filter out duplicate requests
@@ -2500,7 +2478,7 @@ void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
pnode->pindexLastGetBlocksBegin = pindexBegin;
pnode->hashLastGetBlocksEnd = hashEnd;
- pnode->PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
+ pnode->PushMessage("getblocks", chainActive.GetLocator(pindexBegin), hashEnd);
}
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
@@ -2517,7 +2495,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
return error("ProcessBlock() : CheckBlock FAILED");
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
- if (pcheckpoint && pblock->hashPrevBlock != hashBestChain)
+ if (pcheckpoint && pblock->hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
{
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
@@ -2539,7 +2517,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
// If we don't already have its previous block, shunt it off to holding area until we get it
if (pblock->hashPrevBlock != 0 && !mapBlockIndex.count(pblock->hashPrevBlock))
{
- printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().c_str());
+ LogPrintf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().c_str());
// Accept orphans as long as there is a node to request its parents from
if (pfrom) {
@@ -2548,7 +2526,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
// Ask this guy to fill in what we're missing
- PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(pblock2));
+ PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(pblock2));
}
return true;
}
@@ -2578,7 +2556,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapOrphanBlocksByPrev.erase(hashPrev);
}
- printf("ProcessBlock: ACCEPTED\n");
+ LogPrintf("ProcessBlock: ACCEPTED\n");
return true;
}
@@ -2744,7 +2722,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
bool AbortNode(const std::string &strMessage) {
strMiscWarning = strMessage;
- printf("*** %s\n", strMessage.c_str());
+ LogPrintf("*** %s\n", strMessage.c_str());
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
@@ -2775,12 +2753,12 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
if (!file && !fReadOnly)
file = fopen(path.string().c_str(), "wb+");
if (!file) {
- printf("Unable to open file %s\n", path.string().c_str());
+ LogPrintf("Unable to open file %s\n", path.string().c_str());
return NULL;
}
if (pos.nPos) {
if (fseek(file, pos.nPos, SEEK_SET)) {
- printf("Unable to seek to position %u of %s\n", pos.nPos, path.string().c_str());
+ LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string().c_str());
fclose(file);
return NULL;
}
@@ -2843,9 +2821,9 @@ bool static LoadBlockIndexDB()
// Load block file info
pblocktree->ReadLastBlockFile(nLastBlockFile);
- printf("LoadBlockIndexDB(): last block file = %i\n", nLastBlockFile);
+ LogPrintf("LoadBlockIndexDB(): last block file = %i\n", nLastBlockFile);
if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile))
- printf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString().c_str());
+ LogPrintf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString().c_str());
// Load nBestInvalidWork, OK if it doesn't exist
CBigNum bnBestInvalidWork;
@@ -2859,51 +2837,42 @@ bool static LoadBlockIndexDB()
// Check whether we have a transaction index
pblocktree->ReadFlag("txindex", fTxIndex);
- printf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
+ LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
// Load hashBestChain pointer to end of best chain
- pindexBest = pcoinsTip->GetBestBlock();
- if (pindexBest == NULL)
+ chainActive.SetTip(pcoinsTip->GetBestBlock());
+ if (chainActive.Tip() == NULL)
return true;
- hashBestChain = pindexBest->GetBlockHash();
- nBestHeight = pindexBest->nHeight;
- nBestChainWork = pindexBest->nChainWork;
// register best chain
- CBlockIndex *pindex = pindexBest;
- vBlockIndexByHeight.resize(pindexBest->nHeight + 1);
- while(pindex != NULL) {
- vBlockIndexByHeight[pindex->nHeight] = pindex;
- pindex = pindex->pprev;
- }
- printf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
- hashBestChain.ToString().c_str(), nBestHeight,
- DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
+ LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
+ chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(),
+ DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str());
return true;
}
bool VerifyDB(int nCheckLevel, int nCheckDepth)
{
- if (pindexBest == NULL || pindexBest->pprev == NULL)
+ if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL)
return true;
// Verify blocks in the best chain
if (nCheckDepth <= 0)
nCheckDepth = 1000000000; // suffices until the year 19000
- if (nCheckDepth > nBestHeight)
- nCheckDepth = nBestHeight;
+ if (nCheckDepth > chainActive.Height())
+ nCheckDepth = chainActive.Height();
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
- printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
+ LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
CCoinsViewCache coins(*pcoinsTip, true);
- CBlockIndex* pindexState = pindexBest;
+ CBlockIndex* pindexState = chainActive.Tip();
CBlockIndex* pindexFailure = NULL;
int nGoodTransactions = 0;
CValidationState state;
- for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
+ for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
{
boost::this_thread::interruption_point();
- if (pindex->nHeight < nBestHeight-nCheckDepth)
+ if (pindex->nHeight < chainActive.Height()-nCheckDepth)
break;
CBlock block;
// check level 0: read from disk
@@ -2935,14 +2904,14 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
}
}
if (pindexFailure)
- return error("VerifyDB() : *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", pindexBest->nHeight - pindexFailure->nHeight + 1, nGoodTransactions);
+ return error("VerifyDB() : *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
// check level 4: try reconnecting blocks
if (nCheckLevel >= 4) {
CBlockIndex *pindex = pindexState;
- while (pindex != pindexBest) {
+ while (pindex != chainActive.Tip()) {
boost::this_thread::interruption_point();
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
CBlock block;
if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
@@ -2951,7 +2920,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
}
}
- printf("No coin database inconsistencies in last %i blocks (%i transactions)\n", pindexBest->nHeight - pindexState->nHeight, nGoodTransactions);
+ LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions);
return true;
}
@@ -2960,12 +2929,8 @@ void UnloadBlockIndex()
{
mapBlockIndex.clear();
setBlockIndexValid.clear();
- pindexGenesisBlock = NULL;
- nBestHeight = 0;
- nBestChainWork = 0;
+ chainActive.SetTip(NULL);
nBestInvalidWork = 0;
- hashBestChain = 0;
- pindexBest = NULL;
}
bool LoadBlockIndex()
@@ -2979,13 +2944,13 @@ bool LoadBlockIndex()
bool InitBlockIndex() {
// Check whether we're already initialized
- if (pindexGenesisBlock != NULL)
+ if (chainActive.Genesis() != NULL)
return true;
// Use the provided setting for -txindex in the new database
fTxIndex = GetBoolArg("-txindex", false);
pblocktree->WriteFlag("txindex", fTxIndex);
- printf("Initializing databases...\n");
+ LogPrintf("Initializing databases...\n");
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
if (!fReindex) {
@@ -3025,7 +2990,7 @@ void PrintBlockTree()
}
vector<pair<int, CBlockIndex*> > vStack;
- vStack.push_back(make_pair(0, pindexGenesisBlock));
+ vStack.push_back(make_pair(0, chainActive.Genesis()));
int nPrevCol = 0;
while (!vStack.empty())
@@ -3038,25 +3003,25 @@ void PrintBlockTree()
if (nCol > nPrevCol)
{
for (int i = 0; i < nCol-1; i++)
- printf("| ");
- printf("|\\\n");
+ LogPrintf("| ");
+ LogPrintf("|\\\n");
}
else if (nCol < nPrevCol)
{
for (int i = 0; i < nCol; i++)
- printf("| ");
- printf("|\n");
+ LogPrintf("| ");
+ LogPrintf("|\n");
}
nPrevCol = nCol;
// print columns
for (int i = 0; i < nCol; i++)
- printf("| ");
+ LogPrintf("| ");
// print item
CBlock block;
ReadBlockFromDisk(block, pindex);
- printf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"",
+ LogPrintf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"",
pindex->nHeight,
pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()).c_str(),
@@ -3068,7 +3033,7 @@ void PrintBlockTree()
vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++)
{
- if (vNext[i]->GetNextInMainChain())
+ if (chainActive.Next(vNext[i]))
{
swap(vNext[0], vNext[i]);
break;
@@ -3141,7 +3106,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
break;
}
} catch (std::exception &e) {
- printf("%s() : Deserialize or I/O error caught during load\n", __PRETTY_FUNCTION__);
+ LogPrintf("%s() : Deserialize or I/O error caught during load\n", __PRETTY_FUNCTION__);
}
}
fclose(fileIn);
@@ -3149,7 +3114,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
AbortNode(_("Error: system error: ") + e.what());
}
if (nLoaded > 0)
- printf("Loaded %i blocks from external file in %"PRI64d"ms\n", nLoaded, GetTimeMillis() - nStart);
+ LogPrintf("Loaded %i blocks from external file in %"PRI64d"ms\n", nLoaded, GetTimeMillis() - nStart);
return nLoaded > 0;
}
@@ -3315,7 +3280,7 @@ void static ProcessGetData(CNode* pfrom)
// and we want it right after the last block so they don't
// wait for other stuff first.
vector<CInv> vInv;
- vInv.push_back(CInv(MSG_BLOCK, hashBestChain));
+ vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
pfrom->PushMessage("inv", vInv);
pfrom->hashContinue = 0;
}
@@ -3371,11 +3336,10 @@ void static ProcessGetData(CNode* pfrom)
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
RandAddSeedPerfmon();
- if (fDebug)
- printf("received: %s (%"PRIszu" bytes)\n", strCommand.c_str(), vRecv.size());
+ LogPrint("net", "received: %s (%"PRIszu" bytes)\n", strCommand.c_str(), vRecv.size());
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
- printf("dropmessagestest DROPPING RECV MESSAGE\n");
+ LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
return true;
}
@@ -3401,7 +3365,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// Since February 20, 2012, the protocol is initiated at version 209,
// and earlier versions are no longer supported
- printf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion);
+ LogPrintf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion);
pfrom->fDisconnect = true;
return false;
}
@@ -3428,7 +3392,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce && nNonce > 1)
{
- printf("connected to self at %s, disconnecting\n", pfrom->addr.ToString().c_str());
+ LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString().c_str());
pfrom->fDisconnect = true;
return true;
}
@@ -3479,7 +3443,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true;
- printf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
+ LogPrintf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
cPeerBlockCounts.input(pfrom->nStartingHeight);
}
@@ -3592,21 +3556,20 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->AddInventoryKnown(inv);
bool fAlreadyHave = AlreadyHave(inv);
- if (fDebug)
- printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
+ LogPrint("net", " got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
if (!fAlreadyHave) {
if (!fImporting && !fReindex)
pfrom->AskFor(inv);
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
- PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
+ PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
} else if (nInv == nLastBlock) {
// In case we are on a very long side-chain, it is possible that we already have
// the last block in an inv bundle sent in response to getblocks. Try to detect
// this situation and push another getblocks to continue.
PushGetBlocks(pfrom, mapBlockIndex[inv.hash], uint256(0));
if (fDebug)
- printf("force request: %s\n", inv.ToString().c_str());
+ LogPrintf("force request: %s\n", inv.ToString().c_str());
}
// Track requests for our stuff
@@ -3626,10 +3589,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
if (fDebugNet || (vInv.size() != 1))
- printf("received getdata (%"PRIszu" invsz)\n", vInv.size());
+ LogPrint("net", "received getdata (%"PRIszu" invsz)\n", vInv.size());
if ((fDebugNet && vInv.size() > 0) || (vInv.size() == 1))
- printf("received getdata for: %s\n", vInv[0].ToString().c_str());
+ LogPrint("net", "received getdata for: %s\n", vInv[0].ToString().c_str());
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
ProcessGetData(pfrom);
@@ -3643,18 +3606,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> locator >> hashStop;
// Find the last block the caller has in the main chain
- CBlockIndex* pindex = locator.GetBlockIndex();
+ CBlockIndex* pindex = chainActive.FindFork(locator);
// Send the rest of the chain
if (pindex)
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
int nLimit = 500;
- printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
- for (; pindex; pindex = pindex->GetNextInMainChain())
+ LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
+ for (; pindex; pindex = chainActive.Next(pindex))
{
if (pindex->GetBlockHash() == hashStop)
{
- printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
+ LogPrint("net", " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
break;
}
pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
@@ -3662,7 +3625,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// When this block is requested, we'll send an inv that'll make them
// getblocks the next batch of inventory.
- printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
+ LogPrint("net", " getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
pfrom->hashContinue = pindex->GetBlockHash();
break;
}
@@ -3688,16 +3651,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else
{
// Find the last block the caller has in the main chain
- pindex = locator.GetBlockIndex();
+ pindex = chainActive.FindFork(locator);
if (pindex)
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
}
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector<CBlock> vHeaders;
int nLimit = 2000;
- printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
- for (; pindex; pindex = pindex->GetNextInMainChain())
+ LogPrint("net", "getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
+ for (; pindex; pindex = chainActive.Next(pindex))
{
vHeaders.push_back(pindex->GetBlockHeader());
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
@@ -3746,7 +3709,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (mempool.accept(stateDummy, orphanTx, true, &fMissingInputs2))
{
- printf(" accepted orphan tx %s\n", orphanHash.ToString().c_str());
+ LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString().c_str());
RelayTransaction(orphanTx, orphanHash);
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
vWorkQueue.push_back(orphanHash);
@@ -3756,7 +3719,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// invalid or too-little-fee orphan
vEraseQueue.push_back(orphanHash);
- printf(" removed orphan tx %s\n", orphanHash.ToString().c_str());
+ LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString().c_str());
}
mempool.check(pcoinsTip);
}
@@ -3772,11 +3735,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS);
if (nEvicted > 0)
- printf("mapOrphan overflow, removed %u tx\n", nEvicted);
+ LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
}
- int nDoS;
+ int nDoS = 0;
if (state.IsInvalid(nDoS))
- pfrom->Misbehaving(nDoS);
+ if (nDoS > 0)
+ pfrom->Misbehaving(nDoS);
}
@@ -3785,7 +3749,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CBlock block;
vRecv >> block;
- printf("received block %s\n", block.GetHash().ToString().c_str());
+ LogPrint("net", "received block %s\n", block.GetHash().ToString().c_str());
// block.print();
CInv inv(MSG_BLOCK, block.GetHash());
@@ -3794,9 +3758,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CValidationState state;
if (ProcessBlock(state, pfrom, &block))
mapAlreadyAskedFor.erase(inv);
- int nDoS;
+ int nDoS = 0;
if (state.IsInvalid(nDoS))
- pfrom->Misbehaving(nDoS);
+ if (nDoS > 0)
+ pfrom->Misbehaving(nDoS);
}
@@ -3850,6 +3815,63 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
+ else if (strCommand == "pong")
+ {
+ int64 pingUsecEnd = GetTimeMicros();
+ uint64 nonce = 0;
+ size_t nAvail = vRecv.in_avail();
+ bool bPingFinished = false;
+ std::string sProblem;
+
+ if (nAvail >= sizeof(nonce)) {
+ vRecv >> nonce;
+
+ // Only process pong message if there is an outstanding ping (old ping without nonce should never pong)
+ if (pfrom->nPingNonceSent != 0) {
+ if (nonce == pfrom->nPingNonceSent) {
+ // Matching pong received, this ping is no longer outstanding
+ bPingFinished = true;
+ int64 pingUsecTime = pingUsecEnd - pfrom->nPingUsecStart;
+ if (pingUsecTime > 0) {
+ // Successful ping time measurement, replace previous
+ pfrom->nPingUsecTime = pingUsecTime;
+ } else {
+ // This should never happen
+ sProblem = "Timing mishap";
+ }
+ } else {
+ // Nonce mismatches are normal when pings are overlapping
+ sProblem = "Nonce mismatch";
+ if (nonce == 0) {
+ // This is most likely a bug in another implementation somewhere, cancel this ping
+ bPingFinished = true;
+ sProblem = "Nonce zero";
+ }
+ }
+ } else {
+ sProblem = "Unsolicited pong without ping";
+ }
+ } else {
+ // This is most likely a bug in another implementation somewhere, cancel this ping
+ bPingFinished = true;
+ sProblem = "Short payload";
+ }
+
+ if (!(sProblem.empty())) {
+ LogPrint("net", "pong %s %s: %s, %"PRI64x" expected, %"PRI64x" received, %"PRIszu" bytes\n",
+ pfrom->addr.ToString().c_str(),
+ pfrom->strSubVer.c_str(),
+ sProblem.c_str(),
+ pfrom->nPingNonceSent,
+ nonce,
+ nAvail);
+ }
+ if (bPingFinished) {
+ pfrom->nPingNonceSent = 0;
+ }
+ }
+
+
else if (strCommand == "alert")
{
CAlert alert;
@@ -3948,7 +3970,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
bool ProcessMessages(CNode* pfrom)
{
//if (fDebug)
- // printf("ProcessMessages(%zu messages)\n", pfrom->vRecvMsg.size());
+ // LogPrintf("ProcessMessages(%"PRIszu" messages)\n", pfrom->vRecvMsg.size());
//
// Message format
@@ -3973,7 +3995,7 @@ bool ProcessMessages(CNode* pfrom)
CNetMessage& msg = *it;
//if (fDebug)
- // printf("ProcessMessages(message %u msgsz, %zu bytes, complete:%s)\n",
+ // LogPrintf("ProcessMessages(message %u msgsz, %"PRIszu" bytes, complete:%s)\n",
// msg.hdr.nMessageSize, msg.vRecv.size(),
// msg.complete() ? "Y" : "N");
@@ -3986,7 +4008,7 @@ bool ProcessMessages(CNode* pfrom)
// Scan for message start
if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
- printf("\n\nPROCESSMESSAGE: INVALID MESSAGESTART\n\n");
+ LogPrintf("\n\nPROCESSMESSAGE: INVALID MESSAGESTART\n\n");
fOk = false;
break;
}
@@ -3995,7 +4017,7 @@ bool ProcessMessages(CNode* pfrom)
CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid())
{
- printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
+ LogPrintf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
continue;
}
string strCommand = hdr.GetCommand();
@@ -4010,7 +4032,7 @@ bool ProcessMessages(CNode* pfrom)
memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum)
{
- printf("ProcessMessages(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
+ LogPrintf("ProcessMessages(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
continue;
}
@@ -4030,12 +4052,12 @@ bool ProcessMessages(CNode* pfrom)
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
- printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
+ LogPrintf("ProcessMessages(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
}
else if (strstr(e.what(), "size too large"))
{
// Allow exceptions from over-long size
- printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
+ LogPrintf("ProcessMessages(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
}
else
{
@@ -4052,7 +4074,7 @@ bool ProcessMessages(CNode* pfrom)
}
if (!fRet)
- printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
+ LogPrintf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
}
// In case the connection got shut down, its receive buffer was wiped
@@ -4071,20 +4093,40 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (pto->nVersion == 0)
return true;
- // Keep-alive ping. We send a nonce of zero because we don't use it anywhere
- // right now.
+ //
+ // Message: ping
+ //
+ bool pingSend = false;
+ if (pto->fPingQueued) {
+ // RPC ping request by user
+ pingSend = true;
+ }
if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSendMsg.empty()) {
+ // Ping automatically sent as a keepalive
+ pingSend = true;
+ }
+ if (pingSend) {
uint64 nonce = 0;
- if (pto->nVersion > BIP0031_VERSION)
+ while (nonce == 0) {
+ RAND_bytes((unsigned char*)&nonce, sizeof(nonce));
+ }
+ pto->nPingNonceSent = nonce;
+ pto->fPingQueued = false;
+ if (pto->nVersion > BIP0031_VERSION) {
+ // Take timestamp as close as possible before transmitting ping
+ pto->nPingUsecStart = GetTimeMicros();
pto->PushMessage("ping", nonce);
- else
+ } else {
+ // Peer is too old to support ping command with nonce, pong will never arrive, disable timing
+ pto->nPingUsecStart = 0;
pto->PushMessage("ping");
+ }
}
// Start block sync
if (pto->fStartSync && !fImporting && !fReindex) {
pto->fStartSync = false;
- PushGetBlocks(pto, pindexBest, uint256(0));
+ PushGetBlocks(pto, chainActive.Tip(), uint256(0));
}
// Resend wallet transactions that haven't gotten in a block yet
@@ -4215,7 +4257,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (!AlreadyHave(inv))
{
if (fDebugNet)
- printf("sending getdata: %s\n", inv.ToString().c_str());
+ LogPrint("net", "sending getdata: %s\n", inv.ToString().c_str());
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
diff --git a/src/main.h b/src/main.h
index a690a2bc9c..fc60ccc0b5 100644
--- a/src/main.h
+++ b/src/main.h
@@ -5,6 +5,10 @@
#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "core.h"
#include "bignum.h"
#include "sync.h"
@@ -70,20 +74,12 @@ extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
-extern std::vector<CBlockIndex*> vBlockIndexByHeight;
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
-extern CBlockIndex* pindexGenesisBlock;
-extern int nBestHeight;
-extern uint256 nBestChainWork;
extern uint256 nBestInvalidWork;
-extern uint256 hashBestChain;
-extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
extern uint64 nLastBlockTx;
extern uint64 nLastBlockSize;
extern const std::string strMessageMagic;
-extern double dHashesPerSec;
-extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
@@ -151,8 +147,6 @@ void UnloadBlockIndex();
bool VerifyDB(int nCheckLevel, int nCheckDepth);
/** Print the loaded block tree */
void PrintBlockTree();
-/** Find a block by height in the currently-connected chain */
-CBlockIndex* FindBlockByHeight(int nHeight);
/** Process protocol messages received from a given node */
bool ProcessMessages(CNode* pfrom);
/** Send queued protocol messages to be sent to a give node */
@@ -651,7 +645,7 @@ public:
if (nBlocks==0 || nTimeFirst > nTimeIn)
nTimeFirst = nTimeIn;
nBlocks++;
- if (nHeightIn > nHeightFirst)
+ if (nHeightIn > nHeightLast)
nHeightLast = nHeightIn;
if (nTimeIn > nTimeLast)
nTimeLast = nTimeIn;
@@ -817,15 +811,6 @@ public:
return (CBigNum(1)<<256) / (bnTarget+1);
}
- bool IsInMainChain() const
- {
- return nHeight < (int)vBlockIndexByHeight.size() && vBlockIndexByHeight[nHeight] == this;
- }
-
- CBlockIndex *GetNextInMainChain() const {
- return nHeight+1 >= (int)vBlockIndexByHeight.size() ? NULL : vBlockIndexByHeight[nHeight+1];
- }
-
bool CheckIndex() const
{
return CheckProofOfWork(GetBlockHash(), nBits);
@@ -847,17 +832,7 @@ public:
return pbegin[(pend - pbegin)/2];
}
- int64 GetMedianTime() const
- {
- const CBlockIndex* pindex = this;
- for (int i = 0; i < nMedianTimeSpan/2; i++)
- {
- if (!pindex->GetNextInMainChain())
- return GetBlockTime();
- pindex = pindex->GetNextInMainChain();
- }
- return pindex->GetMedianTimePast();
- }
+ int64 GetMedianTime() const;
/**
* Returns true if there are nRequired or more blocks of minVersion or above
@@ -868,15 +843,15 @@ public:
std::string ToString() const
{
- return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
- pprev, GetNextInMainChain(), nHeight,
+ return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
+ pprev, nHeight,
hashMerkleRoot.ToString().c_str(),
GetBlockHash().ToString().c_str());
}
void print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
};
@@ -958,7 +933,7 @@ public:
void print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
};
@@ -1009,64 +984,67 @@ public:
}
};
+/** An in-memory indexed chain of blocks. */
+class CChain {
+private:
+ std::vector<CBlockIndex*> vChain;
-
-
-
-
-
-/** Describes a place in the block chain to another node such that if the
- * other node doesn't have the same branch, it can find a recent common trunk.
- * The further back it is, the further before the fork it may be.
- */
-class CBlockLocator
-{
-protected:
- std::vector<uint256> vHave;
public:
- CBlockLocator() {}
+ /** Returns the index entry for the genesis block of this chain, or NULL if none. */
+ CBlockIndex *Genesis() const {
+ return vChain.size() > 0 ? vChain[0] : NULL;
+ }
- explicit CBlockLocator(const CBlockIndex* pindex)
- {
- Set(pindex);
+ /** Returns the index entry for the tip of this chain, or NULL if none. */
+ CBlockIndex *Tip() const {
+ return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
}
- explicit CBlockLocator(uint256 hashBlock);
+ /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
+ CBlockIndex *operator[](int nHeight) const {
+ if (nHeight < 0 || nHeight >= (int)vChain.size())
+ return NULL;
+ return vChain[nHeight];
+ }
- CBlockLocator(const std::vector<uint256>& vHaveIn)
- {
- vHave = vHaveIn;
+ /** Compare two chains efficiently. */
+ friend bool operator==(const CChain &a, const CChain &b) {
+ return a.vChain.size() == b.vChain.size() &&
+ a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
}
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vHave);
- )
+ /** Efficiently check whether a block is present in this chain. */
+ bool Contains(const CBlockIndex *pindex) const {
+ return (*this)[pindex->nHeight] == pindex;
+ }
- void SetNull()
- {
- vHave.clear();
+ /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
+ CBlockIndex *Next(const CBlockIndex *pindex) const {
+ if (Contains(pindex))
+ return (*this)[pindex->nHeight + 1];
+ else
+ return NULL;
}
- bool IsNull()
- {
- return vHave.empty();
+ /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
+ int Height() const {
+ return vChain.size() - 1;
}
- /** Given a block initialises the locator to that point in the chain. */
- void Set(const CBlockIndex* pindex);
- /** Returns the distance in blocks this locator is from our chain head. */
- int GetDistanceBack();
- /** Returns the first best-chain block the locator contains. */
- CBlockIndex* GetBlockIndex();
- /** Returns the hash of the first best chain block the locator contains. */
- uint256 GetBlockHash();
- /** Returns the height of the first best chain block the locator has. */
- int GetHeight();
+ /** Set/initialize a chain with a given tip. Returns the forking point. */
+ CBlockIndex *SetTip(CBlockIndex *pindex);
+
+ /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
+ CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
+
+ /** Find the last common block between this chain and a locator. */
+ CBlockIndex *FindFork(const CBlockLocator &locator) const;
};
+/** The currently-connected chain of blocks. */
+extern CChain chainActive;
+
+
@@ -1082,7 +1060,7 @@ public:
std::map<uint256, CTransaction> mapTx;
std::map<COutPoint, CInPoint> mapNextTx;
- bool accept(CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs);
+ bool accept(CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee = false);
bool addUnchecked(const uint256& hash, const CTransaction &tx);
bool remove(const CTransaction &tx, bool fRecursive = false);
bool removeConflicts(const CTransaction &tx);
@@ -1210,7 +1188,7 @@ public:
@see CTransaction::FetchInputs
*/
int64 GetValueIn(const CTransaction& tx);
-
+
// Check whether all prevouts of the transaction are present in the UTXO set represented by this view
bool HaveInputs(const CTransaction& tx);
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
deleted file mode 100644
index 51830f2342..0000000000
--- a/src/makefile.linux-mingw
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright (c) 2009-2010 Satoshi Nakamoto
-# Distributed under the MIT/X11 software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-DEPSDIR:=/usr/i586-mingw32msvc
-
-CC := i586-mingw32msvc-gcc
-CXX := i586-mingw32msvc-g++
-
-USE_UPNP:=0
-USE_IPV6:=1
-
-INCLUDEPATHS= \
- -I"$(CURDIR)" \
- -I"$(CURDIR)"/obj \
- -I"$(DEPSDIR)/boost_1_50_0" \
- -I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
- -I"$(DEPSDIR)/openssl-1.0.1c/include" \
- -I"$(DEPSDIR)"
-
-LIBPATHS= \
- -L"$(DEPSDIR)/boost_1_50_0/stage/lib" \
- -L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
- -L"$(DEPSDIR)/openssl-1.0.1c"
-
-LIBS= \
- $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a \
- -l boost_system-mt-s \
- -l boost_filesystem-mt-s \
- -l boost_program_options-mt-s \
- -l boost_thread_win32-mt-s \
- -l boost_chrono-mt-s \
- -l db_cxx \
- -l ssl \
- -l crypto
-
-DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
-DEBUGFLAGS=-g
-xCXXFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) $(CXXFLAGS)
-# enable: ASLR, DEP and large address aware
-xLDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -Wl,--large-address-aware $(LDFLAGS)
-
-TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
-
-ifndef USE_UPNP
- override USE_UPNP = -
-endif
-ifneq (${USE_UPNP}, -)
- LIBPATHS += -L"$(DEPSDIR)/miniupnpc"
- LIBS += -l miniupnpc -l iphlpapi
- DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
-endif
-
-ifneq (${USE_IPV6}, -)
- DEFS += -DUSE_IPV6=$(USE_IPV6)
-endif
-
-LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
-
-# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
-HEADERS = $(wildcard *.h)
-
-OBJS= \
- leveldb/libleveldb.a \
- obj/alert.o \
- obj/version.o \
- obj/checkpoints.o \
- obj/netbase.o \
- obj/addrman.o \
- obj/crypter.o \
- obj/key.o \
- obj/db.o \
- obj/init.o \
- obj/bitcoind.o \
- obj/keystore.o \
- obj/core.o \
- obj/main.o \
- obj/miner.o \
- obj/net.o \
- obj/protocol.o \
- obj/bitcoinrpc.o \
- obj/rpcdump.o \
- obj/rpcnet.o \
- obj/rpcmining.o \
- obj/rpcwallet.o \
- obj/rpcblockchain.o \
- obj/rpcrawtransaction.o \
- obj/script.o \
- obj/sync.o \
- obj/util.o \
- obj/wallet.o \
- obj/walletdb.o \
- obj/noui.o \
- obj/hash.o \
- obj/bloom.o \
- obj/leveldb.o \
- obj/txdb.o \
- obj/chainparams.o
-
-all: bitcoind.exe
-
-DEFS += -I"$(CURDIR)/leveldb/include"
-DEFS += -I"$(CURDIR)/leveldb/helpers"
-leveldb/libleveldb.a:
- @echo "Building LevelDB ..." && cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && i586-mingw32msvc-ranlib libleveldb.a && i586-mingw32msvc-ranlib libmemenv.a && cd ..
-
-obj/build.h: FORCE
- /bin/sh ../share/genbuild.sh obj/build.h
-version.cpp: obj/build.h
-DEFS += -DHAVE_BUILD_INFO
-
-obj/%.o: %.cpp $(HEADERS)
- $(CXX) -c $(xCXXFLAGS) -o $@ $<
-
-bitcoind.exe: $(OBJS:obj/%=obj/%)
- $(CXX) $(xCXXFLAGS) $(xLDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
-
-TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
-
-obj-test/%.o: test/%.cpp $(HEADERS)
- $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -o $@ $<
-
-test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
- $(CXX) $(xCXXFLAGS) $(xLDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS)
-
-
-clean:
- -rm -f obj/*.o
- -rm -f bitcoind.exe
- -rm -f obj-test/*.o
- -rm -f test_bitcoin.exe
- -rm -f obj/build.h
- cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) clean && cd ..
-
-FORCE:
diff --git a/src/makefile.mingw b/src/makefile.mingw
deleted file mode 100644
index cb989d8ae8..0000000000
--- a/src/makefile.mingw
+++ /dev/null
@@ -1,143 +0,0 @@
-# Copyright (c) 2009-2010 Satoshi Nakamoto
-# Distributed under the MIT/X11 software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-# Makefile for the MinGW g++ compiler/toolchain
-#
-# Assumes Berkeley DB, Boost, and OpenSSL have all been compiled and installed
-# into /usr/local (/usr/local/include, /usr/local/lib).
-#
-# If dependencies are somewhere else, run 'make DEPSDIR=/path/'
-#
-# Boost libraries are given wacky names that include the particular version of
-# boost you're using; set BOOST_SUFFIX appropriately.
-#
-# 'make clean' assumes it is running inside a MSYS shell, and uses 'rm'
-# to remove files.
-
-CXX ?= g++
-
-USE_UPNP:=-
-USE_IPV6:=1
-
-DEPSDIR?=/usr/local
-BOOST_SUFFIX?=-mgw46-mt-s-1_52
-
-INCLUDEPATHS= \
- -I"$(CURDIR)" \
- -I"$(DEPSDIR)/include"
-
-LIBPATHS= \
- -L"$(CURDIR)/leveldb" \
- -L"$(DEPSDIR)/lib"
-
-LIBS= \
- -l leveldb \
- -l memenv \
- -l boost_system$(BOOST_SUFFIX) \
- -l boost_filesystem$(BOOST_SUFFIX) \
- -l boost_program_options$(BOOST_SUFFIX) \
- -l boost_thread$(BOOST_SUFFIX) \
- -l boost_chrono$(BOOST_SUFFIX) \
- -l db_cxx \
- -l ssl \
- -l crypto
-
-DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
-DEBUGFLAGS=-g
-CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
-# enable: ASLR, DEP and large address aware
-LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -Wl,--large-address-aware
-
-TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
-
-ifndef USE_UPNP
- override USE_UPNP = -
-endif
-ifneq (${USE_UPNP}, -)
- LIBS += -l miniupnpc -l iphlpapi
- DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
-endif
-
-ifneq (${USE_IPV6}, -)
- DEFS += -DUSE_IPV6=$(USE_IPV6)
-endif
-
-LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
-
-# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
-HEADERS = $(wildcard *.h)
-
-OBJS= \
- leveldb/libleveldb.a \
- obj/alert.o \
- obj/version.o \
- obj/checkpoints.o \
- obj/netbase.o \
- obj/addrman.o \
- obj/crypter.o \
- obj/key.o \
- obj/db.o \
- obj/init.o \
- obj/bitcoind.o \
- obj/keystore.o \
- obj/core.o \
- obj/main.o \
- obj/miner.o \
- obj/net.o \
- obj/protocol.o \
- obj/bitcoinrpc.o \
- obj/rpcdump.o \
- obj/rpcnet.o \
- obj/rpcmining.o \
- obj/rpcwallet.o \
- obj/rpcblockchain.o \
- obj/rpcrawtransaction.o \
- obj/script.o \
- obj/sync.o \
- obj/util.o \
- obj/wallet.o \
- obj/walletdb.o \
- obj/hash.o \
- obj/bloom.o \
- obj/noui.o \
- obj/leveldb.o \
- obj/txdb.o \
- obj/chainparams.o
-
-
-all: bitcoind.exe
-
-test check: test_bitcoin.exe FORCE
- test_bitcoin.exe
-
-#
-# LevelDB support
-#
-DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
-DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
-
-leveldb/libleveldb.a:
- cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(CFLAGS)" TARGET_OS=NATIVE_WINDOWS libleveldb.a libmemenv.a && cd ..
-
-obj/%.o: %.cpp $(HEADERS)
- $(CXX) -c $(CFLAGS) -o $@ $<
-
-bitcoind.exe: $(OBJS:obj/%=obj/%)
- $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
-
-TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
-
-obj-test/%.o: test/%.cpp $(HEADERS)
- $(CXX) -c $(TESTDEFS) $(CFLAGS) -o $@ $<
-
-test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
- $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework$(BOOST_SUFFIX) $(LIBS)
-
-clean:
- rm -f bitcoind.exe test_bitcoin.exe
- rm -f obj/*
- rm -f obj-test/*
- cd leveldb && $(MAKE) TARGET_OS=NATIVE_WINDOWS clean && cd ..
-
-FORCE:
diff --git a/src/makefile.osx b/src/makefile.osx
deleted file mode 100644
index ee364f5c4a..0000000000
--- a/src/makefile.osx
+++ /dev/null
@@ -1,181 +0,0 @@
-# -*- mode: Makefile; -*-
-# Copyright (c) 2011 Bitcoin Developers
-# Distributed under the MIT/X11 software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-# Mac OS X makefile for bitcoin
-# Originally by Laszlo Hanyecz (solar@heliacal.net)
-
-CXX=llvm-g++
-DEPSDIR=/opt/local
-
-INCLUDEPATHS= \
- -I"$(CURDIR)" \
- -I"$(CURDIR)"/obj \
- -I"$(DEPSDIR)/include" \
- -I"$(DEPSDIR)/include/db48"
-
-LIBPATHS= \
- -L"$(DEPSDIR)/lib" \
- -L"$(DEPSDIR)/lib/db48"
-
-USE_UPNP:=1
-USE_IPV6:=1
-
-LIBS= -dead_strip
-
-TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
-
-ifdef STATIC
-# Build STATIC if you are redistributing the bitcoind binary
-TESTLIBS += \
- $(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
-LIBS += \
- $(DEPSDIR)/lib/db48/libdb_cxx-4.8.a \
- $(DEPSDIR)/lib/libboost_system-mt.a \
- $(DEPSDIR)/lib/libboost_filesystem-mt.a \
- $(DEPSDIR)/lib/libboost_program_options-mt.a \
- $(DEPSDIR)/lib/libboost_thread-mt.a \
- $(DEPSDIR)/lib/libboost_chrono-mt.a \
- $(DEPSDIR)/lib/libssl.a \
- $(DEPSDIR)/lib/libcrypto.a \
- -lz
-else
-TESTLIBS += \
- -lboost_unit_test_framework-mt
-LIBS += \
- -ldb_cxx-4.8 \
- -lboost_system-mt \
- -lboost_filesystem-mt \
- -lboost_program_options-mt \
- -lboost_thread-mt \
- -lboost_chrono-mt \
- -lssl \
- -lcrypto \
- -lz
-TESTDEFS += -DBOOST_TEST_DYN_LINK
-endif
-
-DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE
-
-ifdef RELEASE
-# Compile for maximum compatibility and smallest size.
-# This requires that dependencies are compiled
-# the same way.
-CFLAGS = -mmacosx-version-min=10.5 -arch i386 -O3
-else
-DEBUGFLAGS = -g
-endif
-
-# ppc doesn't work because we don't support big-endian
-CFLAGS += -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
- $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
-
-OBJS= \
- leveldb/libleveldb.a \
- obj/alert.o \
- obj/version.o \
- obj/checkpoints.o \
- obj/netbase.o \
- obj/addrman.o \
- obj/crypter.o \
- obj/key.o \
- obj/db.o \
- obj/init.o \
- obj/bitcoind.o \
- obj/keystore.o \
- obj/core.o \
- obj/main.o \
- obj/miner.o \
- obj/net.o \
- obj/protocol.o \
- obj/bitcoinrpc.o \
- obj/rpcdump.o \
- obj/rpcnet.o \
- obj/rpcmining.o \
- obj/rpcwallet.o \
- obj/rpcblockchain.o \
- obj/rpcrawtransaction.o \
- obj/script.o \
- obj/sync.o \
- obj/util.o \
- obj/wallet.o \
- obj/walletdb.o \
- obj/hash.o \
- obj/bloom.o \
- obj/noui.o \
- obj/leveldb.o \
- obj/txdb.o \
- obj/chainparams.o
-
-ifndef USE_UPNP
- override USE_UPNP = -
-endif
-ifneq (${USE_UPNP}, -)
- DEFS += -DUSE_UPNP=$(USE_UPNP)
-ifdef STATIC
- LIBS += $(DEPSDIR)/lib/libminiupnpc.a
-else
- LIBS += -lminiupnpc
-endif
-endif
-
-ifneq (${USE_IPV6}, -)
- DEFS += -DUSE_IPV6=$(USE_IPV6)
-endif
-
-all: bitcoind
-
-test check: test_bitcoin FORCE
- ./test_bitcoin
-
-#
-# LevelDB support
-#
-LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
-DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
-DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
-leveldb/libleveldb.a:
- @echo "Building LevelDB ..." && cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(CFLAGS)" libleveldb.a libmemenv.a && cd ..
-
-# auto-generated dependencies:
--include obj/*.P
--include obj-test/*.P
-
-obj/build.h: FORCE
- /bin/sh ../share/genbuild.sh obj/build.h
-version.cpp: obj/build.h
-DEFS += -DHAVE_BUILD_INFO
-
-obj/%.o: %.cpp
- $(CXX) -c $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
- @cp $(@:%.o=%.d) $(@:%.o=%.P); \
- sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
- -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
- rm -f $(@:%.o=%.d)
-
-bitcoind: $(OBJS:obj/%=obj/%)
- $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
-
-TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
-
-obj-test/%.o: test/%.cpp
- $(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
- @cp $(@:%.o=%.d) $(@:%.o=%.P); \
- sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
- -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
- rm -f $(@:%.o=%.d)
-
-test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
- $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) $(TESTLIBS)
-
-clean:
- -rm -f bitcoind test_bitcoin
- -rm -f obj/*.o
- -rm -f obj-test/*.o
- -rm -f obj/*.P
- -rm -f obj-test/*.P
- -rm -f obj/build.h
- -cd leveldb && $(MAKE) clean || true
-
-FORCE:
diff --git a/src/makefile.unix b/src/makefile.unix
deleted file mode 100644
index 55fd594f93..0000000000
--- a/src/makefile.unix
+++ /dev/null
@@ -1,206 +0,0 @@
-# Copyright (c) 2009-2010 Satoshi Nakamoto
-# Distributed under the MIT/X11 software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-# :=0 --> UPnP support turned off by default at runtime
-# :=1 --> UPnP support turned on by default at runtime
-# :=- --> No UPnP support - miniupnp not required
-USE_UPNP:=0
-
-# :=1 --> Enable IPv6 support
-# :=0 --> Disable IPv6 support
-USE_IPV6:=1
-
-LINK:=$(CXX)
-
-DEFS=-DBOOST_SPIRIT_THREADSAFE -DBOOST_NO_CXX11_VARIADIC_TEMPLATES -D_FILE_OFFSET_BITS=64
-
-DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
-LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
-
-TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
-
-LMODE = dynamic
-LMODE2 = dynamic
-ifdef STATIC
- LMODE = static
- ifeq (${STATIC}, all)
- LMODE2 = static
- endif
-else
- TESTDEFS += -DBOOST_TEST_DYN_LINK
-endif
-
-# for boost 1.37, add -mt to the boost libraries
-LIBS += \
- -Wl,-B$(LMODE) \
- -l boost_system$(BOOST_LIB_SUFFIX) \
- -l boost_filesystem$(BOOST_LIB_SUFFIX) \
- -l boost_program_options$(BOOST_LIB_SUFFIX) \
- -l boost_thread$(BOOST_LIB_SUFFIX) \
- -l db_cxx$(BDB_LIB_SUFFIX) \
- -l ssl \
- -l crypto
-
-TESTLIBS += \
- -Wl,-B$(LMODE) \
- -l boost_unit_test_framework$(BOOST_LIB_SUFFIX)
-
-ifndef USE_UPNP
- override USE_UPNP = -
-endif
-ifneq (${USE_UPNP}, -)
- LIBS += -l miniupnpc
- DEFS += -DUSE_UPNP=$(USE_UPNP)
-endif
-
-ifneq (${USE_IPV6}, -)
- DEFS += -DUSE_IPV6=$(USE_IPV6)
-endif
-
-LIBS+= \
- -Wl,-B$(LMODE2) \
- -l z \
- -l dl \
- -l pthread
-
-
-# Hardening
-# Make some classes of vulnerabilities unexploitable in case one is discovered.
-#
- # This is a workaround for Ubuntu bug #691722, the default -fstack-protector causes
- # -fstack-protector-all to be ignored unless -fno-stack-protector is used first.
- # see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722
- HARDENING=-fno-stack-protector
-
- # Stack Canaries
- # Put numbers at the beginning of each stack frame and check that they are the same.
- # If a stack buffer if overflowed, it writes over the canary number and then on return
- # when that number is checked, it won't be the same and the program will exit with
- # a "Stack smashing detected" error instead of being exploited.
- HARDENING+=-fstack-protector-all -Wstack-protector
-
- # Make some important things such as the global offset table read only as soon as
- # the dynamic linker is finished building it. This will prevent overwriting of addresses
- # which would later be jumped to.
- LDHARDENING+=-Wl,-z,relro -Wl,-z,now
-
- # Build position independent code to take advantage of Address Space Layout Randomization
- # offered by some kernels.
- # see doc/build-unix.txt for more information.
- ifdef PIE
- HARDENING+=-fPIE
- LDHARDENING+=-pie
- endif
-
- # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in
- # the source such overflowing a statically defined buffer.
- HARDENING+=-D_FORTIFY_SOURCE=2
-#
-
-
-DEBUGFLAGS=-g
-
-# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
-# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
-xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
- $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
-
-# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
-# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
-xLDFLAGS=$(LDHARDENING) $(LDFLAGS)
-
-OBJS= \
- leveldb/libleveldb.a \
- obj/alert.o \
- obj/version.o \
- obj/checkpoints.o \
- obj/netbase.o \
- obj/addrman.o \
- obj/crypter.o \
- obj/key.o \
- obj/db.o \
- obj/init.o \
- obj/bitcoind.o \
- obj/keystore.o \
- obj/core.o \
- obj/main.o \
- obj/miner.o \
- obj/net.o \
- obj/protocol.o \
- obj/bitcoinrpc.o \
- obj/rpcdump.o \
- obj/rpcnet.o \
- obj/rpcmining.o \
- obj/rpcwallet.o \
- obj/rpcblockchain.o \
- obj/rpcrawtransaction.o \
- obj/script.o \
- obj/sync.o \
- obj/util.o \
- obj/wallet.o \
- obj/walletdb.o \
- obj/hash.o \
- obj/bloom.o \
- obj/noui.o \
- obj/leveldb.o \
- obj/txdb.o \
- obj/chainparams.o
-
-
-all: bitcoind
-
-test check: test_bitcoin FORCE
- ./test_bitcoin
-
-#
-# LevelDB support
-#
-MAKEOVERRIDES =
-LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
-DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
-DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
-leveldb/libleveldb.a:
- @echo "Building LevelDB ..." && cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && cd ..
-
-# auto-generated dependencies:
--include obj/*.P
--include obj-test/*.P
-
-obj/build.h: FORCE
- /bin/sh ../share/genbuild.sh obj/build.h
-version.cpp: obj/build.h
-DEFS += -DHAVE_BUILD_INFO
-
-obj/%.o: %.cpp
- $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
- @cp $(@:%.o=%.d) $(@:%.o=%.P); \
- sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
- -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
- rm -f $(@:%.o=%.d)
-
-bitcoind: $(OBJS:obj/%=obj/%)
- $(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS)
-
-TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
-
-obj-test/%.o: test/%.cpp
- $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
- @cp $(@:%.o=%.d) $(@:%.o=%.P); \
- sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
- -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
- rm -f $(@:%.o=%.d)
-
-test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
- $(LINK) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ $(TESTLIBS) $(xLDFLAGS) $(LIBS)
-
-clean:
- -rm -f bitcoind test_bitcoin
- -rm -f obj/*.o
- -rm -f obj-test/*.o
- -rm -f obj/*.P
- -rm -f obj-test/*.P
- -rm -f obj/build.h
- -cd leveldb && $(MAKE) clean || true
-
-FORCE:
diff --git a/src/miner.cpp b/src/miner.cpp
index 3ecf1609e1..e9c1d9aff9 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -3,15 +3,11 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core.h"
-#include "wallet.h"
#include "miner.h"
#include "main.h"
-
-
-
-
+double dHashesPerSec = 0.0;
+int64 nHPSTimerStart = 0;
//////////////////////////////////////////////////////////////////////////////
//
@@ -106,10 +102,10 @@ public:
void print() const
{
- printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
+ LogPrintf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
ptx->GetHash().ToString().c_str(), dPriority, dFeePerKb);
BOOST_FOREACH(uint256 hash, setDependsOn)
- printf(" setDependsOn %s\n", hash.ToString().c_str());
+ LogPrintf(" setDependsOn %s\n", hash.ToString().c_str());
}
};
@@ -180,7 +176,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
int64 nFees = 0;
{
LOCK2(cs_main, mempool.cs);
- CBlockIndex* pindexPrev = pindexBest;
+ CBlockIndex* pindexPrev = chainActive.Tip();
CCoinsViewCache view(*pcoinsTip, true);
// Priority order to process transactions
@@ -211,7 +207,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// or other transactions in the memory pool.
if (!mempool.mapTx.count(txin.prevout.hash))
{
- printf("ERROR: mempool transaction missing input\n");
+ LogPrintf("ERROR: mempool transaction missing input\n");
if (fDebug) assert("mempool transaction missing input" == 0);
fMissingInputs = true;
if (porphan)
@@ -331,7 +327,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if (fPrintPriority)
{
- printf("priority %.1f feeperkb %.1f txid %s\n",
+ LogPrintf("priority %.1f feeperkb %.1f txid %s\n",
dPriority, dFeePerKb, tx.GetHash().ToString().c_str());
}
@@ -355,7 +351,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
- printf("CreateNewBlock(): total size %"PRI64u"\n", nBlockSize);
+ LogPrintf("CreateNewBlock(): total size %"PRI64u"\n", nBlockSize);
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
pblocktemplate->vTxFees[0] = -nFees;
@@ -463,15 +459,15 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
return false;
//// debug print
- printf("BitcoinMiner:\n");
- printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
+ LogPrintf("BitcoinMiner:\n");
+ LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
pblock->print();
- printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
+ LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
// Found a solution
{
LOCK(cs_main);
- if (pblock->hashPrevBlock != hashBestChain)
+ if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
return error("BitcoinMiner : generated block is stale");
// Remove key from key pool
@@ -494,7 +490,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
void static BitcoinMiner(CWallet *pwallet)
{
- printf("BitcoinMiner started\n");
+ LogPrintf("BitcoinMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("bitcoin-miner");
@@ -514,7 +510,7 @@ void static BitcoinMiner(CWallet *pwallet)
// Create new block
//
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
- CBlockIndex* pindexPrev = pindexBest;
+ CBlockIndex* pindexPrev = chainActive.Tip();
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
if (!pblocktemplate.get())
@@ -522,7 +518,7 @@ void static BitcoinMiner(CWallet *pwallet)
CBlock *pblock = &pblocktemplate->block;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
- printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
+ LogPrintf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
//
@@ -603,7 +599,7 @@ void static BitcoinMiner(CWallet *pwallet)
if (GetTime() - nLogTime > 30 * 60)
{
nLogTime = GetTime();
- printf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
+ LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
}
}
}
@@ -617,7 +613,7 @@ void static BitcoinMiner(CWallet *pwallet)
break;
if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
break;
- if (pindexPrev != pindexBest)
+ if (pindexPrev != chainActive.Tip())
break;
// Update nTime every few seconds
@@ -633,7 +629,7 @@ void static BitcoinMiner(CWallet *pwallet)
} }
catch (boost::thread_interrupted)
{
- printf("BitcoinMiner terminated\n");
+ LogPrintf("BitcoinMiner terminated\n");
throw;
}
}
diff --git a/src/miner.h b/src/miner.h
index 36d58be00f..7e60b9e53b 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -22,4 +22,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
/** Base sha256 mining transform */
void SHA256Transform(void* pstate, void* pinput, const void* pinit);
+extern double dHashesPerSec;
+extern int64 nHPSTimerStart;
+
#endif // BITCOIN_MINER_H
diff --git a/src/net.cpp b/src/net.cpp
index 1f461e55db..99457be0f5 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -3,6 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "chainparams.h"
#include "db.h"
#include "net.h"
@@ -28,6 +32,9 @@
// Dump addresses to peers.dat every 15 minutes (900s)
#define DUMP_ADDRESSES_INTERVAL 900
+#if !defined(HAVE_MSG_NOSIGNAL)
+#define MSG_NOSIGNAL 0
+#endif
using namespace std;
using namespace boost;
@@ -166,14 +173,14 @@ bool RecvLine(SOCKET hSocket, string& strLine)
if (nBytes == 0)
{
// socket closed
- printf("socket closed\n");
+ LogPrint("net", "socket closed\n");
return false;
}
else
{
// socket error
int nErr = WSAGetLastError();
- printf("recv failed: %d\n", nErr);
+ LogPrint("net", "recv failed: %d\n", nErr);
return false;
}
}
@@ -219,7 +226,7 @@ bool AddLocal(const CService& addr, int nScore)
if (IsLimited(addr))
return false;
- printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
+ LogPrintf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
{
LOCK(cs_mapLocalHost);
@@ -327,7 +334,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
strLine.resize(strLine.size()-1);
CService addr(strLine,0,true);
- printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
+ LogPrintf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
if (!addr.IsValid() || !addr.IsRoutable())
return false;
ipRet.SetIP(addr);
@@ -402,7 +409,7 @@ void ThreadGetMyExternalIP()
CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
- printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
+ LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
AddLocal(addrLocalHost, LOCAL_HTTP);
}
}
@@ -419,8 +426,10 @@ void AddressCurrentlyConnected(const CService& addr)
-
-
+uint64 CNode::nTotalBytesRecv = 0;
+uint64 CNode::nTotalBytesSent = 0;
+CCriticalSection CNode::cs_totalBytesRecv;
+CCriticalSection CNode::cs_totalBytesSent;
CNode* FindNode(const CNetAddr& ip)
{
@@ -466,7 +475,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
/// debug print
- printf("trying connection %s lastseen=%.1fhrs\n",
+ LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
pszDest ? pszDest : addrConnect.ToString().c_str(),
pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
@@ -476,17 +485,16 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
{
addrman.Attempt(addrConnect);
- /// debug print
- printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
+ LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
// Set to non-blocking
#ifdef WIN32
u_long nOne = 1;
if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
- printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
+ LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
#else
if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
- printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
+ LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
#endif
// Add node
@@ -512,7 +520,7 @@ void CNode::CloseSocketDisconnect()
fDisconnect = true;
if (hSocket != INVALID_SOCKET)
{
- printf("disconnecting node %s\n", addrName.c_str());
+ LogPrint("net", "disconnecting node %s\n", addrName.c_str());
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
@@ -534,12 +542,14 @@ void CNode::Cleanup()
void CNode::PushVersion()
{
+ int nBestHeight = g_signals.GetHeight().get_value_or(0);
+
/// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
CAddress addrMe = GetLocalAddress(&addr);
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
- printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
+ LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
}
@@ -576,7 +586,7 @@ bool CNode::Misbehaving(int howmuch)
{
if (addr.IsLocal())
{
- printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
+ LogPrintf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
return false;
}
@@ -584,7 +594,7 @@ bool CNode::Misbehaving(int howmuch)
if (nMisbehavior >= GetArg("-banscore", 100))
{
int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
- printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
+ LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
{
LOCK(cs_setBanned);
if (setBanned[addr] < banTime)
@@ -593,7 +603,7 @@ bool CNode::Misbehaving(int howmuch)
CloseSocketDisconnect();
return true;
} else
- printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
+ LogPrintf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
return false;
}
@@ -614,6 +624,21 @@ void CNode::copyStats(CNodeStats &stats)
X(nSendBytes);
X(nRecvBytes);
stats.fSyncNode = (this == pnodeSync);
+
+ // It is common for nodes with good ping times to suddenly become lagged,
+ // due to a new block arriving or other large transfer.
+ // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
+ // since pingtime does not update until the ping is complete, which might take a while.
+ // So, if a ping is taking an unusually long time in flight,
+ // the caller can immediately detect that this is happening.
+ int64 nPingUsecWait = 0;
+ if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
+ nPingUsecWait = GetTimeMicros() - nPingUsecStart;
+ }
+
+ // Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
+ stats.dPingTime = (((double)nPingUsecTime) / 1e6);
+ stats.dPingWait = (((double)nPingUsecWait) / 1e6);
}
#undef X
@@ -710,6 +735,7 @@ void SocketSendData(CNode *pnode)
pnode->nLastSend = GetTime();
pnode->nSendBytes += nBytes;
pnode->nSendOffset += nBytes;
+ pnode->RecordBytesSent(nBytes);
if (pnode->nSendOffset == data.size()) {
pnode->nSendOffset = 0;
pnode->nSendSize -= data.size();
@@ -724,7 +750,7 @@ void SocketSendData(CNode *pnode)
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
- printf("socket send error %d\n", nErr);
+ LogPrintf("socket send error %d\n", nErr);
pnode->CloseSocketDisconnect();
}
}
@@ -805,10 +831,9 @@ void ThreadSocketHandler()
}
}
}
- if (vNodes.size() != nPrevNodeCount)
- {
+ if(vNodes.size() != nPrevNodeCount) {
nPrevNodeCount = vNodes.size();
- uiInterface.NotifyNumConnectionsChanged(vNodes.size());
+ uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
}
@@ -884,7 +909,7 @@ void ThreadSocketHandler()
if (have_fds)
{
int nErr = WSAGetLastError();
- printf("socket select error %d\n", nErr);
+ LogPrintf("socket select error %d\n", nErr);
for (unsigned int i = 0; i <= hSocketMax; i++)
FD_SET(i, &fdsetRecv);
}
@@ -912,7 +937,7 @@ void ThreadSocketHandler()
if (hSocket != INVALID_SOCKET)
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
- printf("Warning: Unknown socket family\n");
+ LogPrintf("Warning: Unknown socket family\n");
{
LOCK(cs_vNodes);
@@ -925,7 +950,7 @@ void ThreadSocketHandler()
{
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK)
- printf("socket error accept failed: %d\n", nErr);
+ LogPrintf("socket error accept failed: %d\n", nErr);
}
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
{
@@ -937,12 +962,12 @@ void ThreadSocketHandler()
}
else if (CNode::IsBanned(addr))
{
- printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
+ LogPrintf("connection from %s dropped (banned)\n", addr.ToString().c_str());
closesocket(hSocket);
}
else
{
- printf("accepted connection %s\n", addr.ToString().c_str());
+ LogPrint("net", "accepted connection %s\n", addr.ToString().c_str());
CNode* pnode = new CNode(hSocket, addr, "", true);
pnode->AddRef();
{
@@ -987,12 +1012,13 @@ void ThreadSocketHandler()
pnode->CloseSocketDisconnect();
pnode->nLastRecv = GetTime();
pnode->nRecvBytes += nBytes;
+ pnode->RecordBytesRecv(nBytes);
}
else if (nBytes == 0)
{
// socket closed gracefully
if (!pnode->fDisconnect)
- printf("socket closed\n");
+ LogPrint("net", "socket closed\n");
pnode->CloseSocketDisconnect();
}
else if (nBytes < 0)
@@ -1002,7 +1028,7 @@ void ThreadSocketHandler()
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
if (!pnode->fDisconnect)
- printf("socket recv error %d\n", nErr);
+ LogPrintf("socket recv error %d\n", nErr);
pnode->CloseSocketDisconnect();
}
}
@@ -1031,17 +1057,17 @@ void ThreadSocketHandler()
{
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
- printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
+ LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
pnode->fDisconnect = true;
}
else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
{
- printf("socket not sending\n");
+ LogPrintf("socket not sending\n");
pnode->fDisconnect = true;
}
else if (GetTime() - pnode->nLastRecv > 90*60)
{
- printf("socket inactivity timeout\n");
+ LogPrintf("socket inactivity timeout\n");
pnode->fDisconnect = true;
}
}
@@ -1093,16 +1119,16 @@ void ThreadMapPort()
char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
- printf("UPnP: GetExternalIPAddress() returned %d\n", r);
+ LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
else
{
if(externalIPAddress[0])
{
- printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
+ LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
}
else
- printf("UPnP: GetExternalIPAddress failed.\n");
+ LogPrintf("UPnP: GetExternalIPAddress failed.\n");
}
}
@@ -1121,10 +1147,10 @@ void ThreadMapPort()
#endif
if(r!=UPNPCOMMAND_SUCCESS)
- printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
+ LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
else
- printf("UPnP Port Mapping successful.\n");;
+ LogPrintf("UPnP Port Mapping successful.\n");;
MilliSleep(20*60*1000); // Refresh every 20 minutes
}
@@ -1132,13 +1158,13 @@ void ThreadMapPort()
catch (boost::thread_interrupted)
{
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
- printf("UPNP_DeletePortMapping() returned : %d\n", r);
+ LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r);
freeUPNPDevlist(devlist); devlist = 0;
FreeUPNPUrls(&urls);
throw;
}
} else {
- printf("No valid UPnP IGDs found\n");
+ LogPrintf("No valid UPnP IGDs found\n");
freeUPNPDevlist(devlist); devlist = 0;
if (r != 0)
FreeUPNPUrls(&urls);
@@ -1183,7 +1209,7 @@ void ThreadDNSAddressSeed()
const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
int found = 0;
- printf("Loading addresses from DNS seeds (could take a while)\n");
+ LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
if (HaveNameProxy()) {
@@ -1206,7 +1232,7 @@ void ThreadDNSAddressSeed()
}
}
- printf("%d addresses found from DNS seeds\n", found);
+ LogPrintf("%d addresses found from DNS seeds\n", found);
}
@@ -1227,7 +1253,7 @@ void DumpAddresses()
CAddrDB adb;
adb.Write(addrman);
- printf("Flushed %d addresses to peers.dat %"PRI64d"ms\n",
+ LogPrint("net", "Flushed %d addresses to peers.dat %"PRI64d"ms\n",
addrman.size(), GetTimeMillis() - nStart);
}
@@ -1285,7 +1311,7 @@ void ThreadOpenConnections()
if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
static bool done = false;
if (!done) {
- printf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
+ LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
done = true;
}
@@ -1461,6 +1487,8 @@ void static StartSync(const vector<CNode*> &vNodes) {
CNode *pnodeNewSync = NULL;
double dBestScore = 0;
+ int nBestHeight = g_signals.GetHeight().get_value_or(0);
+
// Iterate over all nodes
BOOST_FOREACH(CNode* pnode, vNodes) {
// check preconditions for allowing a sync
@@ -1561,7 +1589,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
{
strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
- printf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1569,7 +1597,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
if (hListenSocket == INVALID_SOCKET)
{
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1593,7 +1621,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
#endif
{
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1624,16 +1652,16 @@ bool BindListenPort(const CService &addrBind, string& strError)
strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin is probably already running."), addrBind.ToString().c_str());
else
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
- printf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
- printf("Bound to %s\n", addrBind.ToString().c_str());
+ LogPrintf("Bound to %s\n", addrBind.ToString().c_str());
// Listen for incoming connections
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1680,7 +1708,7 @@ void static Discover()
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
CNetAddr addr(s4->sin_addr);
if (AddLocal(addr, LOCAL_IF))
- printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
+ LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
}
#ifdef USE_IPV6
else if (ifa->ifa_addr->sa_family == AF_INET6)
@@ -1688,7 +1716,7 @@ void static Discover()
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
CNetAddr addr(s6->sin6_addr);
if (AddLocal(addr, LOCAL_IF))
- printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
+ LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
}
#endif
}
@@ -1719,7 +1747,7 @@ void StartNode(boost::thread_group& threadGroup)
//
if (!GetBoolArg("-dnsseed", true))
- printf("DNS seeding disabled\n");
+ LogPrintf("DNS seeding disabled\n");
else
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
@@ -1746,7 +1774,7 @@ void StartNode(boost::thread_group& threadGroup)
bool StopNode()
{
- printf("StopNode()\n");
+ LogPrintf("StopNode()\n");
MapPort(false);
if (semOutbound)
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
@@ -1772,7 +1800,7 @@ public:
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
if (hListenSocket != INVALID_SOCKET)
if (closesocket(hListenSocket) == SOCKET_ERROR)
- printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
+ LogPrintf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
// clean up some globals (to help leak detection)
BOOST_FOREACH(CNode *pnode, vNodes)
@@ -1838,3 +1866,27 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
pnode->PushInventory(inv);
}
}
+
+void CNode::RecordBytesRecv(uint64 bytes)
+{
+ LOCK(cs_totalBytesRecv);
+ nTotalBytesRecv += bytes;
+}
+
+void CNode::RecordBytesSent(uint64 bytes)
+{
+ LOCK(cs_totalBytesSent);
+ nTotalBytesSent += bytes;
+}
+
+uint64 CNode::GetTotalBytesRecv()
+{
+ LOCK(cs_totalBytesRecv);
+ return nTotalBytesRecv;
+}
+
+uint64 CNode::GetTotalBytesSent()
+{
+ LOCK(cs_totalBytesSent);
+ return nTotalBytesSent;
+}
diff --git a/src/net.h b/src/net.h
index 686861fbeb..9b76d1643d 100644
--- a/src/net.h
+++ b/src/net.h
@@ -28,7 +28,6 @@ static const unsigned int MAX_INV_SZ = 50000;
class CNode;
class CBlockIndex;
-extern int nBestHeight;
@@ -52,6 +51,7 @@ void SocketSendData(CNode *pnode);
// Signals for message handling
struct CNodeSignals
{
+ boost::signals2::signal<int ()> GetHeight;
boost::signals2::signal<bool (CNode*)> ProcessMessages;
boost::signals2::signal<bool (CNode*, bool)> SendMessages;
};
@@ -119,6 +119,8 @@ public:
uint64 nSendBytes;
uint64 nRecvBytes;
bool fSyncNode;
+ double dPingTime;
+ double dPingWait;
};
@@ -234,6 +236,12 @@ public:
CCriticalSection cs_inventory;
std::multimap<int64, CInv> mapAskFor;
+ // Ping time measurement
+ uint64 nPingNonceSent;
+ int64 nPingUsecStart;
+ int64 nPingUsecTime;
+ bool fPingQueued;
+
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, MIN_PROTO_VERSION)
{
nServices = 0;
@@ -268,6 +276,10 @@ public:
fRelayTxes = false;
setInventoryKnown.max_size(SendBufferSize() / 1000);
pfilter = new CBloomFilter();
+ nPingNonceSent = 0;
+ nPingUsecStart = 0;
+ nPingUsecTime = 0;
+ fPingQueued = false;
// Be shy and don't send version until we hear
if (hSocket != INVALID_SOCKET && !fInbound)
@@ -286,8 +298,15 @@ public:
}
private:
+ // Network usage totals
+ static CCriticalSection cs_totalBytesRecv;
+ static CCriticalSection cs_totalBytesSent;
+ static uint64 nTotalBytesRecv;
+ static uint64 nTotalBytesSent;
+
CNode(const CNode&);
void operator=(const CNode&);
+
public:
@@ -301,7 +320,7 @@ public:
unsigned int GetTotalRecvSize()
{
unsigned int total = 0;
- BOOST_FOREACH(const CNetMessage &msg, vRecvMsg)
+ BOOST_FOREACH(const CNetMessage &msg, vRecvMsg)
total += msg.vRecv.size() + 24;
return total;
}
@@ -372,8 +391,7 @@ public:
nRequestTime = it->second;
else
nRequestTime = 0;
- if (fDebugNet)
- printf("askfor %s %"PRI64d" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
+ LogPrint("net", "askfor %s %"PRI64d" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
// Make sure not to reuse time indexes to keep things in the same order
int64 nNow = (GetTime() - 1) * 1000000;
@@ -399,8 +417,7 @@ public:
ENTER_CRITICAL_SECTION(cs_vSend);
assert(ssSend.size() == 0);
ssSend << CMessageHeader(pszCommand, 0);
- if (fDebug)
- printf("sending: %s ", pszCommand);
+ LogPrint("net", "sending: %s ", pszCommand);
}
// TODO: Document the precondition of this function. Is cs_vSend locked?
@@ -410,8 +427,7 @@ public:
LEAVE_CRITICAL_SECTION(cs_vSend);
- if (fDebug)
- printf("(aborted)\n");
+ LogPrint("net", "(aborted)\n");
}
// TODO: Document the precondition of this function. Is cs_vSend locked?
@@ -419,7 +435,7 @@ public:
{
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
- printf("dropmessages DROPPING SEND MESSAGE\n");
+ LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
AbortMessage();
return;
}
@@ -438,9 +454,7 @@ public:
assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
- if (fDebug) {
- printf("(%d bytes)\n", nSize);
- }
+ LogPrint("net", "(%d bytes)\n", nSize);
std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
ssSend.GetAndClear(*it);
@@ -639,6 +653,13 @@ public:
static bool IsBanned(CNetAddr ip);
bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
void copyStats(CNodeStats &stats);
+
+ // Network stats
+ static void RecordBytesRecv(uint64 bytes);
+ static void RecordBytesSent(uint64 bytes);
+
+ static uint64 GetTotalBytesRecv();
+ static uint64 GetTotalBytesSent();
};
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 348771375c..360ecdd959 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -15,6 +15,10 @@
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
+#if !defined(HAVE_MSG_NOSIGNAL)
+#define MSG_NOSIGNAL 0
+#endif
+
using namespace std;
// Settings
@@ -165,7 +169,7 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
bool static Socks4(const CService &addrDest, SOCKET& hSocket)
{
- printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str());
+ LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString().c_str());
if (!addrDest.IsIPv4())
{
closesocket(hSocket);
@@ -200,16 +204,16 @@ bool static Socks4(const CService &addrDest, SOCKET& hSocket)
{
closesocket(hSocket);
if (pchRet[1] != 0x5b)
- printf("ERROR: Proxy returned error %d\n", pchRet[1]);
+ LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]);
return false;
}
- printf("SOCKS4 connected %s\n", addrDest.ToString().c_str());
+ LogPrintf("SOCKS4 connected %s\n", addrDest.ToString().c_str());
return true;
}
bool static Socks5(string strDest, int port, SOCKET& hSocket)
{
- printf("SOCKS5 connecting %s\n", strDest.c_str());
+ LogPrintf("SOCKS5 connecting %s\n", strDest.c_str());
if (strDest.size() > 255)
{
closesocket(hSocket);
@@ -305,7 +309,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
closesocket(hSocket);
return error("Error reading from proxy");
}
- printf("SOCKS5 connected %s\n", strDest.c_str());
+ LogPrintf("SOCKS5 connected %s\n", strDest.c_str());
return true;
}
@@ -320,7 +324,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
#endif
socklen_t len = sizeof(sockaddr);
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
- printf("Cannot connect to %s: unsupported network\n", addrConnect.ToString().c_str());
+ LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString().c_str());
return false;
}
@@ -359,13 +363,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
if (nRet == 0)
{
- printf("connection timeout\n");
+ LogPrint("net", "connection timeout\n");
closesocket(hSocket);
return false;
}
if (nRet == SOCKET_ERROR)
{
- printf("select() for connection failed: %i\n",WSAGetLastError());
+ LogPrintf("select() for connection failed: %i\n",WSAGetLastError());
closesocket(hSocket);
return false;
}
@@ -376,13 +380,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
#endif
{
- printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
+ LogPrintf("getsockopt() for connection failed: %i\n",WSAGetLastError());
closesocket(hSocket);
return false;
}
if (nRet != 0)
{
- printf("connect() failed after select(): %s\n",strerror(nRet));
+ LogPrintf("connect() failed after select(): %s\n",strerror(nRet));
closesocket(hSocket);
return false;
}
@@ -393,7 +397,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
else
#endif
{
- printf("connect() failed: %i\n",WSAGetLastError());
+ LogPrintf("connect() failed: %i\n",WSAGetLastError());
closesocket(hSocket);
return false;
}
@@ -860,7 +864,7 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
nBits = 4;
}
// for he.net, use /36 groups
- else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
+ else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
nBits = 36;
// for the rest of the IPv6 network, use /32 groups
else
@@ -889,7 +893,7 @@ uint64 CNetAddr::GetHash() const
void CNetAddr::print() const
{
- printf("CNetAddr(%s)\n", ToString().c_str());
+ LogPrintf("CNetAddr(%s)\n", ToString().c_str());
}
// private extensions to enum Network, only returned by GetExtNetwork,
@@ -1130,7 +1134,7 @@ std::string CService::ToString() const
void CService::print() const
{
- printf("CService(%s)\n", ToString().c_str());
+ LogPrintf("CService(%s)\n", ToString().c_str());
}
void CService::SetPort(unsigned short portIn)
diff --git a/src/netbase.h b/src/netbase.h
index e4ec4ef597..e1f80b4ee8 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -4,6 +4,10 @@
#ifndef BITCOIN_NETBASE_H
#define BITCOIN_NETBASE_H
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include <string>
#include <vector>
@@ -50,7 +54,7 @@ class CNetAddr
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
- bool IsRFC4193() const; // IPv6 unique local (FC00::/15)
+ bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
diff --git a/src/noui.cpp b/src/noui.cpp
index c0e00c4715..67eac944c6 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -27,7 +27,7 @@ static bool noui_ThreadSafeMessageBox(const std::string& message, const std::str
strCaption += caption; // Use supplied caption (can be empty)
}
- printf("%s: %s\n", strCaption.c_str(), message.c_str());
+ LogPrintf("%s: %s\n", strCaption.c_str(), message.c_str());
fprintf(stderr, "%s: %s\n", strCaption.c_str(), message.c_str());
return false;
}
@@ -39,7 +39,7 @@ static bool noui_ThreadSafeAskFee(int64 /*nFeeRequired*/)
static void noui_InitMessage(const std::string &message)
{
- printf("init message: %s\n", message.c_str());
+ LogPrintf("init message: %s\n", message.c_str());
}
void noui_connect()
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 745b4338e4..ba254be3e1 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -67,7 +67,7 @@ bool CMessageHeader::IsValid() const
// Message size
if (nMessageSize > MAX_SIZE)
{
- printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
+ LogPrintf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
return false;
}
@@ -146,6 +146,6 @@ std::string CInv::ToString() const
void CInv::print() const
{
- printf("CInv(%s)\n", ToString().c_str());
+ LogPrintf("CInv(%s)\n", ToString().c_str());
}
diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am
new file mode 100644
index 0000000000..e7ae0a905f
--- /dev/null
+++ b/src/qt/Makefile.am
@@ -0,0 +1,172 @@
+include $(top_srcdir)/src/Makefile.include
+
+AM_CPPFLAGS = $(INCLUDES) -I$(top_builddir)/src/obj \
+ -I$(top_srcdir)/src/leveldb/include -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/leveldb/helpers -I$(top_builddir)/src/qt \
+ -I$(top_builddir)/src/qt/forms $(BOOST_INCLUDES) $(PROTOBUF_CFLAGS) \
+ $(QR_CFLAGS) $(BDB_CPPFLAGS)
+AM_LDFLAGS = $(PTHREAD_CFLAGS)
+bin_PROGRAMS = bitcoin-qt
+noinst_LIBRARIES = libbitcoinqt.a
+SUBDIRS = $(BUILD_TEST_QT)
+DIST_SUBDIRS = test
+
+# bitcoin qt core #
+QT_TS = locale/bitcoin_ach.ts locale/bitcoin_af_ZA.ts locale/bitcoin_ar.ts \
+ locale/bitcoin_be_BY.ts locale/bitcoin_bg.ts locale/bitcoin_bs.ts \
+ locale/bitcoin_ca_ES.ts locale/bitcoin_ca.ts locale/bitcoin_cs.ts \
+ locale/bitcoin_cy.ts locale/bitcoin_da.ts locale/bitcoin_de.ts \
+ locale/bitcoin_el_GR.ts locale/bitcoin_en.ts locale/bitcoin_eo.ts \
+ locale/bitcoin_es_CL.ts locale/bitcoin_es.ts locale/bitcoin_et.ts \
+ locale/bitcoin_eu_ES.ts locale/bitcoin_fa_IR.ts locale/bitcoin_fa.ts \
+ locale/bitcoin_fi.ts locale/bitcoin_fr_CA.ts locale/bitcoin_fr.ts \
+ locale/bitcoin_gu_IN.ts locale/bitcoin_he.ts locale/bitcoin_hi_IN.ts \
+ locale/bitcoin_hr.ts locale/bitcoin_hu.ts locale/bitcoin_id_ID.ts \
+ locale/bitcoin_it.ts locale/bitcoin_ja.ts locale/bitcoin_kk_KZ.ts \
+ locale/bitcoin_ko_KR.ts locale/bitcoin_la.ts locale/bitcoin_lt.ts \
+ locale/bitcoin_lv_LV.ts locale/bitcoin_ms_MY.ts locale/bitcoin_nb.ts \
+ locale/bitcoin_nl.ts locale/bitcoin_pl.ts locale/bitcoin_pt_BR.ts \
+ locale/bitcoin_pt_PT.ts locale/bitcoin_ro_RO.ts locale/bitcoin_ru.ts \
+ locale/bitcoin_sk.ts locale/bitcoin_sq.ts locale/bitcoin_sr.ts \
+ locale/bitcoin_sv.ts locale/bitcoin_th_TH.ts locale/bitcoin_tr.ts \
+ locale/bitcoin_uk.ts locale/bitcoin_vi.ts locale/bitcoin_vi_VN.ts \
+ locale/bitcoin_zh_CN.ts locale/bitcoin_zh_TW.ts
+
+QT_FORMS_UI = forms/aboutdialog.ui forms/addressbookpage.ui \
+ forms/askpassphrasedialog.ui forms/editaddressdialog.ui forms/intro.ui \
+ forms/optionsdialog.ui forms/overviewpage.ui forms/qrcodedialog.ui \
+ forms/rpcconsole.ui forms/sendcoinsdialog.ui forms/sendcoinsentry.ui \
+ forms/signverifymessagedialog.ui forms/transactiondescdialog.ui
+
+QT_MOC_CPP = moc_aboutdialog.cpp moc_addressbookpage.cpp \
+ moc_addresstablemodel.cpp moc_askpassphrasedialog.cpp \
+ moc_bitcoinaddressvalidator.cpp moc_bitcoinamountfield.cpp \
+ moc_bitcoingui.cpp moc_bitcoinunits.cpp moc_clientmodel.cpp \
+ moc_csvmodelwriter.cpp moc_editaddressdialog.cpp moc_guiutil.cpp \
+ moc_intro.cpp moc_macdockiconhandler.cpp moc_macnotificationhandler.cpp \
+ moc_monitoreddatamapper.cpp moc_notificator.cpp moc_optionsdialog.cpp \
+ moc_optionsmodel.cpp moc_overviewpage.cpp moc_paymentserver.cpp \
+ moc_qrcodedialog.cpp moc_qvalidatedlineedit.cpp moc_qvaluecombobox.cpp \
+ moc_rpcconsole.cpp moc_sendcoinsdialog.cpp moc_sendcoinsentry.cpp \
+ moc_signverifymessagedialog.cpp moc_splashscreen.cpp moc_trafficgraphwidget.cpp moc_transactiondesc.cpp \
+ moc_transactiondescdialog.cpp moc_transactionfilterproxy.cpp \
+ moc_transactiontablemodel.cpp moc_transactionview.cpp moc_walletframe.cpp \
+ moc_walletmodel.cpp moc_walletstack.cpp moc_walletview.cpp
+
+BITCOIN_MM = macdockiconhandler.mm macnotificationhandler.mm
+QR_CPP = qrcodedialog.cpp
+
+QT_MOC = intro.moc overviewpage.moc rpcconsole.moc
+
+QT_QRC_CPP = qrc_bitcoin.cpp
+QT_QRC = bitcoin.qrc
+
+PROTOBUF_CC = paymentrequest.pb.cc
+PROTOBUF_H = paymentrequest.pb.h
+PROTOBUF_PROTO = paymentrequest.proto
+
+BITCOIN_QT_H = aboutdialog.h addressbookpage.h addresstablemodel.h \
+ askpassphrasedialog.h bitcoinaddressvalidator.h bitcoinamountfield.h \
+ bitcoingui.h bitcoinunits.h clientmodel.h csvmodelwriter.h \
+ editaddressdialog.h guiconstants.h guiutil.h intro.h macdockiconhandler.h \
+ macnotificationhandler.h monitoreddatamapper.h notificator.h optionsdialog.h \
+ optionsmodel.h overviewpage.h paymentrequestplus.h paymentserver.h \
+ qrcodedialog.h qvalidatedlineedit.h qvaluecombobox.h rpcconsole.h \
+ sendcoinsdialog.h sendcoinsentry.h signverifymessagedialog.h splashscreen.h \
+ trafficgraphwidget.h transactiondescdialog.h transactiondesc.h transactionfilterproxy.h \
+ transactionrecord.h transactiontablemodel.h transactionview.h walletframe.h \
+ walletmodel.h walletmodeltransaction.h walletstack.h walletview.h
+
+RES_ICONS = res/icons/bitcoin.png res/icons/address-book.png \
+ res/icons/quit.png res/icons/send.png res/icons/toolbar.png \
+ res/icons/connect0_16.png res/icons/connect1_16.png \
+ res/icons/connect2_16.png res/icons/connect3_16.png \
+ res/icons/connect4_16.png res/icons/transaction0.png \
+ res/icons/transaction2.png res/icons/clock1.png res/icons/clock2.png \
+ res/icons/clock3.png res/icons/clock4.png res/icons/clock5.png \
+ res/icons/configure.png res/icons/receive.png res/icons/editpaste.png \
+ res/icons/editcopy.png res/icons/add.png res/icons/bitcoin_testnet.png \
+ res/icons/toolbar_testnet.png res/icons/edit.png res/icons/history.png \
+ res/icons/overview.png res/icons/export.png res/icons/synced.png \
+ res/icons/remove.png res/icons/tx_mined.png res/icons/tx_input.png \
+ res/icons/tx_output.png res/icons/tx_inout.png res/icons/lock_closed.png \
+ res/icons/lock_open.png res/icons/key.png res/icons/filesave.png \
+ res/icons/qrcode.png res/icons/debugwindow.png res/icons/bitcoin.ico \
+ res/icons/bitcoin_testnet.ico
+
+BITCOIN_QT_CPP = aboutdialog.cpp addressbookpage.cpp \
+ addresstablemodel.cpp askpassphrasedialog.cpp bitcoinaddressvalidator.cpp \
+ bitcoinamountfield.cpp bitcoin.cpp bitcoingui.cpp \
+ bitcoinunits.cpp clientmodel.cpp csvmodelwriter.cpp editaddressdialog.cpp \
+ guiutil.cpp intro.cpp monitoreddatamapper.cpp notificator.cpp \
+ optionsdialog.cpp optionsmodel.cpp overviewpage.cpp paymentrequestplus.cpp \
+ paymentserver.cpp qvalidatedlineedit.cpp qvaluecombobox.cpp \
+ rpcconsole.cpp sendcoinsdialog.cpp sendcoinsentry.cpp \
+ signverifymessagedialog.cpp splashscreen.cpp trafficgraphwidget.cpp transactiondesc.cpp \
+ transactiondescdialog.cpp transactionfilterproxy.cpp transactionrecord.cpp \
+ transactiontablemodel.cpp transactionview.cpp walletframe.cpp \
+ walletmodel.cpp walletmodeltransaction.cpp walletstack.cpp walletview.cpp
+
+RES_IMAGES = res/images/about.png res/images/splash.png \
+ res/images/splash_testnet.png
+
+RES_MOVIES = res/movies/update_spinner.mng
+
+BITCOIN_RC = res/bitcoin-qt-res.rc
+
+libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
+ -I$(top_srcdir)/src/qt/forms $(QT_DBUS_INCLUDES)
+libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
+ $(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
+
+nodist_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
+ $(PROTOBUF_H) $(QT_QRC_CPP)
+
+BUILT_SOURCES = $(nodist_libbitcoinqt_a_SOURCES)
+
+#Generating these with a half-written protobuf header leads to wacky results.
+#This makes sure it's done.
+$(QT_MOC): $(PROTOBUF_H)
+$(QT_MOC_CPP): $(PROTOBUF_H)
+
+if TARGET_DARWIN
+ libbitcoinqt_a_SOURCES += $(BITCOIN_MM)
+endif
+if TARGET_WINDOWS
+ libbitcoinqt_a_SOURCES += $(BITCOIN_RC)
+endif
+if USE_QRCODE
+ libbitcoinqt_a_SOURCES += $(QR_CPP)
+endif
+#
+
+# bitcoin-qt binary #
+bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
+ -I$(top_srcdir)/src/qt/forms
+bitcoin_qt_SOURCES = bitcoin.cpp
+bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN) $(LIBLEVELDB) $(LIBMEMENV) \
+ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
+
+# forms/foo.h -> forms/ui_foo.h
+QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h))))
+
+#locale/foo.ts -> locale/foo.qm
+QT_QM=$(QT_TS:.ts=.qm)
+
+.PHONY: FORCE
+.SECONDARY: $(QT_QM)
+
+bitcoinstrings.cpp: FORCE
+ $(MAKE) -C $(top_srcdir)/src qt/bitcoinstrings.cpp
+
+translate: bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) $(QR_CPP)
+ @test -n $(LUPDATE) || echo "lupdate is required for updating translations"
+ @$(LUPDATE) $^ -locations relative -no-obsolete -ts locale/bitcoin_en.ts
+
+$(QT_QRC_CPP): $(QT_QRC) $(QT_QM) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H)
+ @cd $(abs_srcdir); test -f $(RCC) && $(RCC) -name bitcoin -o $(abs_builddir)/$@ $< || \
+ echo error: could not build $@
+ $(SED) -i.bak -e '/^\*\*.*Created:/d' $@ && rm $@.bak
+ $(SED) -i.bak -e '/^\*\*.*by:/d' $@ && rm $@.bak
+
+CLEANFILES = $(BUILT_SOURCES) $(QT_QM) $(QT_FORMS_H) *.gcda *.gcno
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 8906174d7d..5b8d44481e 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -1,3 +1,7 @@
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "addressbookpage.h"
#include "ui_addressbookpage.h"
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 03517c657f..921c4443a9 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -7,6 +7,7 @@
#include "base58.h"
#include <QFont>
+#include <QDebug>
const QString AddressTableModel::Send = "S";
const QString AddressTableModel::Receive = "R";
@@ -15,7 +16,8 @@ struct AddressTableEntry
{
enum Type {
Sending,
- Receiving
+ Receiving,
+ Hidden /* QSortFilterProxyModel will filter these out */
};
Type type;
@@ -43,6 +45,20 @@ struct AddressTableEntryLessThan
}
};
+/* Determine address type from address purpose */
+static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
+{
+ AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
+ // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
+ if (strPurpose == "send")
+ addressType = AddressTableEntry::Sending;
+ else if (strPurpose == "receive")
+ addressType = AddressTableEntry::Receiving;
+ else if (strPurpose == "unknown" || strPurpose == "") // if purpose not set, guess
+ addressType = (isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
+ return addressType;
+}
+
// Private implementation
class AddressTablePriv
{
@@ -62,17 +78,9 @@ public:
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
-
- AddressTableEntry::Type addressType;
- const std::string& strPurpose = item.second.purpose;
- if (strPurpose == "send") addressType = AddressTableEntry::Sending;
- else if (strPurpose == "receive") addressType = AddressTableEntry::Receiving;
- else if (strPurpose == "unknown") {
- bool fMine = IsMine(*wallet, address.Get());
- addressType = (fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
- }
- else continue; // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
-
+ bool fMine = IsMine(*wallet, address.Get());
+ AddressTableEntry::Type addressType = translateTransactionType(
+ QString::fromStdString(item.second.purpose), fMine);
const std::string& strName = item.second.name;
cachedAddressTable.append(AddressTableEntry(addressType,
QString::fromStdString(strName),
@@ -80,10 +88,12 @@ public:
}
}
// qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order
+ // Even though the map is already sorted this re-sorting step is needed because the originating map
+ // is sorted by binary address, not by base58() address.
qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
}
- void updateEntry(const QString &address, const QString &label, bool isMine, int status)
+ void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
{
// Find address / label in model
QList<AddressTableEntry>::iterator lower = qLowerBound(
@@ -93,14 +103,14 @@ public:
int lowerIndex = (lower - cachedAddressTable.begin());
int upperIndex = (upper - cachedAddressTable.begin());
bool inModel = (lower != upper);
- AddressTableEntry::Type newEntryType = isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending;
+ AddressTableEntry::Type newEntryType = translateTransactionType(purpose, isMine);
switch(status)
{
case CT_NEW:
if(inModel)
{
- OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_NOW, but entry is already in model\n");
+ qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_NOW, but entry is already in model";
break;
}
parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
@@ -110,7 +120,7 @@ public:
case CT_UPDATED:
if(!inModel)
{
- OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_UPDATED, but entry is not in model\n");
+ qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model";
break;
}
lower->type = newEntryType;
@@ -120,7 +130,7 @@ public:
case CT_DELETED:
if(!inModel)
{
- OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_DELETED, but entry is not in model\n");
+ qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model";
break;
}
parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
@@ -322,10 +332,11 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &par
}
}
-void AddressTableModel::updateEntry(const QString &address, const QString &label, bool isMine, int status)
+void AddressTableModel::updateEntry(const QString &address,
+ const QString &label, bool isMine, const QString &purpose, int status)
{
// Update address book model from Bitcoin core
- priv->updateEntry(address, label, isMine, status);
+ priv->updateEntry(address, label, isMine, purpose, status);
}
QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 48baff5e54..6f532087fe 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -85,7 +85,7 @@ signals:
public slots:
/* Update address list from core.
*/
- void updateEntry(const QString &address, const QString &label, bool isMine, int status);
+ void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
friend class AddressTablePriv;
};
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index f165c11cb1..2b7671f209 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -16,6 +16,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
fCapsLock(false)
{
ui->setupUi(this);
+
ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE);
ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE);
ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE);
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 9c290fa717..78693971da 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -62,7 +62,7 @@ static bool ThreadSafeMessageBox(const std::string& message, const std::string&
}
else
{
- printf("%s: %s\n", caption.c_str(), message.c_str());
+ LogPrintf("%s: %s\n", caption.c_str(), message.c_str());
fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
return false;
}
@@ -91,7 +91,7 @@ static void InitMessage(const std::string &message)
splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(55,55,55));
qApp->processEvents();
}
- printf("init message: %s\n", message.c_str());
+ LogPrintf("init message: %s\n", message.c_str());
}
/*
@@ -155,12 +155,15 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
#if QT_VERSION < 0x050000
void DebugMessageHandler(QtMsgType type, const char * msg)
{
- OutputDebugStringF("%s\n", msg);
+ Q_UNUSED(type);
+ LogPrint("qt", "Bitcoin-Qt: %s\n", msg);
}
#else
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
- OutputDebugStringF("%s\n", qPrintable(msg));
+ Q_UNUSED(type);
+ Q_UNUSED(context);
+ LogPrint("qt", "Bitcoin-Qt: %s\n", qPrintable(msg));
}
#endif
@@ -236,6 +239,12 @@ int main(int argc, char *argv[])
// Install global event filter that makes sure that long tooltips can be word-wrapped
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
+ // Install qDebug() message handler to route to debug.log
+#if QT_VERSION < 0x050000
+ qInstallMsgHandler(DebugMessageHandler);
+#else
+ qInstallMessageHandler(DebugMessageHandler);
+#endif
// ... now GUI settings:
OptionsModel optionsModel;
@@ -255,13 +264,6 @@ int main(int argc, char *argv[])
return 1;
}
- // Install qDebug() message handler to route to debug.log:
-#if QT_VERSION < 0x050000
- qInstallMsgHandler(DebugMessageHandler);
-#else
- qInstallMessageHandler(DebugMessageHandler);
-#endif
-
SplashScreen splash(QPixmap(), 0);
if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false))
{
@@ -300,7 +302,8 @@ int main(int argc, char *argv[])
optionsModel.Upgrade(); // Must be done after AppInit2
PaymentServer::LoadRootCAs();
- paymentServer->initNetManager(optionsModel);
+ paymentServer->setOptionsModel(&optionsModel);
+ paymentServer->initNetManager();
if (splashref)
splash.finish(&window);
diff --git a/src/qt/bitcoinaddressvalidator.h b/src/qt/bitcoinaddressvalidator.h
index 2b6a59367d..b7f4dfee96 100644
--- a/src/qt/bitcoinaddressvalidator.h
+++ b/src/qt/bitcoinaddressvalidator.h
@@ -3,8 +3,8 @@
#include <QValidator>
-/** Base48 entry widget validator.
- Corrects near-miss characters and refuses characters that are no part of base48.
+/** Base58 entry widget validator.
+ Corrects near-miss characters and refuses characters that are not part of base58.
*/
class BitcoinAddressValidator : public QValidator
{
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index d9d4e3b23d..37b8743eff 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -130,9 +130,10 @@ void BitcoinAmountField::setValue(qint64 value)
setText(BitcoinUnits::format(currentUnit, value));
}
-void BitcoinAmountField::setReadOnly(bool fReadeOnly)
+void BitcoinAmountField::setReadOnly(bool fReadOnly)
{
- // TODO ...
+ amount->setReadOnly(fReadOnly);
+ unit->setEnabled(!fReadOnly);
}
void BitcoinAmountField::unitChanged(int idx)
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index ad32c9ea68..23a221120f 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -157,6 +157,8 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
rpcConsole = new RPCConsole(this);
connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
+ // prevents an oben debug window from becoming stuck/unusable on client shutdown
+ connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
// Install event filter to be able to catch status tip events (QEvent::StatusTip)
this->installEventFilter(this);
@@ -233,7 +235,11 @@ void BitcoinGUI::createActions(bool fIsTestnet)
aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin"), this);
aboutAction->setStatusTip(tr("Show information about Bitcoin"));
aboutAction->setMenuRole(QAction::AboutRole);
+#if QT_VERSION < 0x050000
aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
+#else
+ aboutQtAction = new QAction(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
+#endif
aboutQtAction->setStatusTip(tr("Show information about Qt"));
aboutQtAction->setMenuRole(QAction::AboutQtRole);
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
@@ -590,21 +596,28 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
int nMBoxIcon = QMessageBox::Information;
int nNotifyIcon = Notificator::Information;
- // Override title based on style
QString msgType;
- switch (style) {
- case CClientUIInterface::MSG_ERROR:
- msgType = tr("Error");
- break;
- case CClientUIInterface::MSG_WARNING:
- msgType = tr("Warning");
- break;
- case CClientUIInterface::MSG_INFORMATION:
- msgType = tr("Information");
- break;
- default:
- msgType = title; // Use supplied title
+
+ // Prefer supplied title over style based title
+ if (!title.isEmpty()) {
+ msgType = title;
}
+ else {
+ switch (style) {
+ case CClientUIInterface::MSG_ERROR:
+ msgType = tr("Error");
+ break;
+ case CClientUIInterface::MSG_WARNING:
+ msgType = tr("Warning");
+ break;
+ case CClientUIInterface::MSG_INFORMATION:
+ msgType = tr("Information");
+ break;
+ default:
+ break;
+ }
+ }
+ // Append title to "Bitcoin - "
if (!msgType.isEmpty())
strTitle += " - " + msgType;
@@ -625,7 +638,7 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
buttons = QMessageBox::Ok;
- QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons);
+ QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
int r = mBox.exec();
if (ret != NULL)
*ret = r == QMessageBox::Ok;
@@ -670,9 +683,12 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
{
+ if (!clientModel || !clientModel->getOptionsModel())
+ return;
+
QString strMessage = tr("This transaction is over the size limit. You can still send it for a fee of %1, "
"which goes to the nodes that process your transaction and helps to support the network. "
- "Do you want to pay the fee?").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nFeeRequired));
+ "Do you want to pay the fee?").arg(BitcoinUnits::formatWithUnit(clientModel->getOptionsModel()->getDisplayUnit(), nFeeRequired));
QMessageBox::StandardButton retval = QMessageBox::question(
this, tr("Confirm transaction fee"), strMessage,
QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes);
@@ -741,13 +757,9 @@ void BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
walletFrame->handlePaymentRequest(recipient);
}
-void BitcoinGUI::showPaymentACK(QString msg)
+void BitcoinGUI::showPaymentACK(const QString& msg)
{
-#if QT_VERSION < 0x050000
- message(tr("Payment acknowledged"), Qt::escape(msg), CClientUIInterface::MODAL);
-#else
- message(tr("Payment acknowledged"), msg.toHtmlEscaped(), CClientUIInterface::MODAL);
-#endif
+ message(tr("Payment acknowledged"), GUIUtil::HtmlEscape(msg), CClientUIInterface::MODAL);
}
void BitcoinGUI::setEncryptionStatus(int status)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index fc25e867fc..e2dd5dc6bc 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -154,7 +154,7 @@ public slots:
void askFee(qint64 nFeeRequired, bool *payFee);
void handlePaymentRequest(const SendCoinsRecipient& recipient);
- void showPaymentACK(QString msg);
+ void showPaymentACK(const QString& msg);
/** Show incoming transaction notification for new transactions. */
void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address);
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 5cf4dd8111..2bab488135 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -13,6 +13,7 @@
#include <QDateTime>
#include <QTimer>
+#include <QDebug>
static const int64 nClientStartupTime = GetTime();
@@ -23,9 +24,8 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
numBlocksAtStartup(-1), pollTimer(0)
{
pollTimer = new QTimer(this);
- pollTimer->setInterval(MODEL_UPDATE_DELAY);
- pollTimer->start();
connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
+ pollTimer->start(MODEL_UPDATE_DELAY);
subscribeToCoreSignals();
}
@@ -42,7 +42,7 @@ int ClientModel::getNumConnections() const
int ClientModel::getNumBlocks() const
{
- return nBestHeight;
+ return chainActive.Height();
}
int ClientModel::getNumBlocksAtStartup()
@@ -51,10 +51,20 @@ int ClientModel::getNumBlocksAtStartup()
return numBlocksAtStartup;
}
+quint64 ClientModel::getTotalBytesRecv() const
+{
+ return CNode::GetTotalBytesRecv();
+}
+
+quint64 ClientModel::getTotalBytesSent() const
+{
+ return CNode::GetTotalBytesSent();
+}
+
QDateTime ClientModel::getLastBlockDate() const
{
- if (pindexBest)
- return QDateTime::fromTime_t(pindexBest->GetBlockTime());
+ if (chainActive.Tip())
+ return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
else if(!isTestNet())
return QDateTime::fromTime_t(1231006505); // Genesis block's time
else
@@ -63,7 +73,7 @@ QDateTime ClientModel::getLastBlockDate() const
double ClientModel::getVerificationProgress() const
{
- return Checkpoints::GuessVerificationProgress(pindexBest);
+ return Checkpoints::GuessVerificationProgress(chainActive.Tip());
}
void ClientModel::updateTimer()
@@ -85,6 +95,8 @@ void ClientModel::updateTimer()
// ensure we return the maximum of newNumBlocksOfPeers and newNumBlocks to not create weird displays in the GUI
emit numBlocksChanged(newNumBlocks, std::max(newNumBlocksOfPeers, newNumBlocks));
}
+
+ emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
}
void ClientModel::updateNumConnections(int numConnections)
@@ -180,14 +192,14 @@ static void NotifyBlocksChanged(ClientModel *clientmodel)
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
{
- // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections);
+ // Too noisy: qDebug() << "NotifyNumConnectionsChanged : " + QString::number(newNumConnections);
QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
Q_ARG(int, newNumConnections));
}
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
{
- OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status);
+ qDebug() << "NotifyAlertChanged : " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
Q_ARG(int, status));
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index f9d491aa50..925f20acd9 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -35,6 +35,9 @@ public:
int getNumBlocks() const;
int getNumBlocksAtStartup();
+ quint64 getTotalBytesRecv() const;
+ quint64 getTotalBytesSent() const;
+
double getVerificationProgress() const;
QDateTime getLastBlockDate() const;
@@ -60,8 +63,8 @@ private:
int cachedNumBlocks;
int cachedNumBlocksOfPeers;
- bool cachedReindexing;
- bool cachedImporting;
+ bool cachedReindexing;
+ bool cachedImporting;
int numBlocksAtStartup;
@@ -74,6 +77,7 @@ signals:
void numConnectionsChanged(int count);
void numBlocksChanged(int count, int countOfPeers);
void alertsChanged(const QString &warnings);
+ void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
//! Asynchronous message notification
void message(const QString &title, const QString &message, unsigned int style);
diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp
index 8a50bbab3f..ad8e0d618a 100644
--- a/src/qt/csvmodelwriter.cpp
+++ b/src/qt/csvmodelwriter.cpp
@@ -85,4 +85,3 @@ bool CSVModelWriter::write()
return file.error() == QFile::NoError;
}
-
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index bb53021cfd..1e4335c645 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -461,7 +461,7 @@
<customwidgets>
<customwidget>
<class>BitcoinAmountField</class>
- <extends>QSpinBox</extends>
+ <extends>QLineEdit</extends>
<header>bitcoinamountfield.h</header>
</customwidget>
<customwidget>
diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui
index 52e9db3762..1cec9066f8 100644
--- a/src/qt/forms/qrcodedialog.ui
+++ b/src/qt/forms/qrcodedialog.ui
@@ -186,7 +186,7 @@
<customwidgets>
<customwidget>
<class>BitcoinAmountField</class>
- <extends>QSpinBox</extends>
+ <extends>QLineEdit</extends>
<header>bitcoinamountfield.h</header>
</customwidget>
</customwidgets>
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index d1d8ab42a0..54c41ffb67 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -445,10 +445,271 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>&amp;Network Traffic</string>
+ </attribute>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="TrafficGraphWidget" name="trafficGraph" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QSlider" name="sldGraphRange">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>288</number>
+ </property>
+ <property name="pageStep">
+ <number>12</number>
+ </property>
+ <property name="value">
+ <number>6</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblGraphRange">
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnClearTrafficGraph">
+ <property name="text">
+ <string>&amp;Clear</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Totals</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="Line" name="line">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>In:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblBytesIn">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_17">
+ <property name="text">
+ <string>Out:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblBytesOut">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>407</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>TrafficGraphWidget</class>
+ <extends>QWidget</extends>
+ <header>trafficgraphwidget.h</header>
+ <container>1</container>
+ <slots>
+ <slot>clear()</slot>
+ </slots>
+ </customwidget>
+ </customwidgets>
<resources>
<include location="../bitcoin.qrc"/>
</resources>
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 6e17565ab0..2a00fc5455 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -28,7 +28,7 @@
<height>165</height>
</rect>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
+ <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<property name="margin">
<number>0</number>
</property>
diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui
index a2ef9a0a38..5c6afd6c71 100644
--- a/src/qt/forms/sendcoinsentry.ui
+++ b/src/qt/forms/sendcoinsentry.ui
@@ -10,19 +10,13 @@
<height>150</height>
</rect>
</property>
- <property name="windowTitle">
- <string>StackedWidget</string>
- </property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QFrame" name="SendCoinsInsecure">
- <property name="windowTitle">
- <string>Form</string>
- </property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@@ -34,7 +28,7 @@
<number>12</number>
</property>
<item row="5" column="0">
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="amountLabel">
<property name="text">
<string>A&amp;mount:</string>
</property>
@@ -47,7 +41,7 @@
</widget>
</item>
<item row="3" column="0">
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="payToLabel">
<property name="text">
<string>Pay &amp;To:</string>
</property>
@@ -63,7 +57,7 @@
<widget class="BitcoinAmountField" name="payAmount"/>
</item>
<item row="4" column="0">
- <widget class="QLabel" name="label_4">
+ <widget class="QLabel" name="labellLabel">
<property name="text">
<string>&amp;Label:</string>
</property>
@@ -592,9 +586,6 @@
</disabled>
</palette>
</property>
- <property name="windowTitle">
- <string>SecureSend</string>
- </property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
@@ -609,7 +600,7 @@
<number>12</number>
</property>
<item row="4" column="0">
- <widget class="QLabel" name="label_s4">
+ <widget class="QLabel" name="memoLabel_s">
<property name="text">
<string>Memo:</string>
</property>
@@ -622,7 +613,7 @@
</widget>
</item>
<item row="5" column="0">
- <widget class="QLabel" name="label_s1">
+ <widget class="QLabel" name="amountLabel_s">
<property name="text">
<string>A&amp;mount:</string>
</property>
@@ -630,12 +621,12 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
- <cstring>payAmount</cstring>
+ <cstring>payAmount_s</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
- <widget class="QLabel" name="label_s2">
+ <widget class="QLabel" name="payToLabel_s">
<property name="text">
<string>Pay &amp;To:</string>
</property>
@@ -649,15 +640,9 @@
</item>
<item row="5" column="2">
<widget class="BitcoinAmountField" name="payAmount_s">
- <property name="enabled">
- <bool>false</bool>
- </property>
<property name="acceptDrops">
<bool>false</bool>
</property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="3" column="2">
@@ -667,14 +652,17 @@
</property>
<item>
<widget class="QLabel" name="payTo_s">
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2">
- <widget class="QLabel" name="memo_s">
- <property name="text">
- <string>message from merchant</string>
+ <widget class="QLabel" name="memoTextLabel_s">
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
</property>
</widget>
</item>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 7d419b6bd9..4d1a8574d0 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -67,7 +67,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;New Address</translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="+63"/>
+ <location filename="../addressbookpage.cpp" line="+67"/>
<source>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</source>
<translation>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</translation>
</message>
@@ -165,7 +165,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>AddressTableModel</name>
<message>
- <location filename="../addresstablemodel.cpp" line="+144"/>
+ <location filename="../addresstablemodel.cpp" line="+164"/>
<source>Label</source>
<translation>Label</translation>
</message>
@@ -203,7 +203,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Repeat new passphrase</translation>
</message>
<message>
- <location filename="../askpassphrasedialog.cpp" line="+33"/>
+ <location filename="../askpassphrasedialog.cpp" line="+34"/>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;10 or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;10 or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</translation>
</message>
@@ -324,7 +324,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+254"/>
+ <location filename="../bitcoingui.cpp" line="+255"/>
<source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
@@ -623,12 +623,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Information</translation>
</message>
<message>
- <location line="+70"/>
+ <location line="+73"/>
<source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source>
<translation>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</translation>
</message>
<message>
- <location line="-140"/>
+ <location line="-143"/>
<source>Up to date</source>
<translation>Up to date</translation>
</message>
@@ -638,7 +638,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Catching up...</translation>
</message>
<message>
- <location line="+113"/>
+ <location line="+116"/>
<source>Confirm transaction fee</source>
<translation>Confirm transaction fee</translation>
</message>
@@ -666,18 +666,22 @@ Address: %4
</translation>
</message>
<message>
- <location line="+33"/>
- <location line="+23"/>
+ <location line="+34"/>
<source>URI handling</source>
<translation>URI handling</translation>
</message>
<message>
- <location line="-23"/>
- <location line="+23"/>
+ <location line="+0"/>
<source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
</message>
<message>
+ <location line="+27"/>
+ <location line="+2"/>
+ <source>Payment acknowledged</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+17"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</translation>
@@ -696,7 +700,7 @@ Address: %4
<context>
<name>ClientModel</name>
<message>
- <location filename="../clientmodel.cpp" line="+105"/>
+ <location filename="../clientmodel.cpp" line="+106"/>
<source>Network Alert</source>
<translation>Network Alert</translation>
</message>
@@ -800,7 +804,7 @@ Address: %4
<context>
<name>GUIUtil::HelpMessageBox</name>
<message>
- <location filename="../guiutil.cpp" line="+517"/>
+ <location filename="../guiutil.cpp" line="+525"/>
<location line="+13"/>
<source>Bitcoin-Qt</source>
<translation>Bitcoin-Qt</translation>
@@ -879,7 +883,7 @@ Address: %4
<translation>Use a custom data directory:</translation>
</message>
<message>
- <location filename="../intro.cpp" line="+100"/>
+ <location filename="../intro.cpp" line="+105"/>
<source>Error</source>
<translation>Error</translation>
</message>
@@ -1067,7 +1071,7 @@ Address: %4
<translation>&amp;Apply</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+54"/>
+ <location filename="../optionsdialog.cpp" line="+58"/>
<source>default</source>
<translation>default</translation>
</message>
@@ -1177,29 +1181,68 @@ Address: %4
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+108"/>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Cannot start bitcoin: click-to-pay handler</translation>
+ <location filename="../paymentserver.cpp" line="+450"/>
+ <location line="+41"/>
+ <source>Payment request error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Insecure requests to custom payment scripts unsupported</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+38"/>
+ <source>Refund from</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+46"/>
+ <location line="+28"/>
+ <location line="+17"/>
+ <source>Network request error</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
- <location filename="../bitcoin.cpp" line="+92"/>
+ <location filename="../bitcoin.cpp" line="+111"/>
+ <location line="+5"/>
<location filename="../intro.cpp" line="-32"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
- <location line="+1"/>
+ <location line="-4"/>
<source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
<translation>Error: Specified data directory &quot;%1&quot; does not exist.</translation>
</message>
<message>
+ <location line="+4"/>
+ <source>Error: Invalid combination of -regtest and -testnet.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../intro.cpp" line="+1"/>
<source>Error: Specified data directory &quot;%1&quot; can not be created.</source>
<translation>Error: Specified data directory &quot;%1&quot; can not be created.</translation>
</message>
+ <message>
+ <location filename="../paymentserver.cpp" line="-175"/>
+ <source>Requested payment amount (%1) too small</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+126"/>
+ <source>Error communicating with %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Bad response from server %1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QRCodeDialog</name>
@@ -1410,13 +1453,15 @@ Address: %4
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+128"/>
+ <location filename="../sendcoinsdialog.cpp" line="+138"/>
<location line="+5"/>
<location line="+5"/>
<location line="+5"/>
<location line="+6"/>
<location line="+5"/>
- <location line="+5"/>
+ <location line="+50"/>
+ <location line="+145"/>
+ <location line="+9"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -1461,25 +1506,19 @@ Address: %4
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-62"/>
- <location line="+2"/>
- <source>&lt;b&gt;%1&lt;/b&gt; to %2 (%3)</source>
- <translation>&lt;b&gt;%1&lt;/b&gt; to %2 (%3)</translation>
- </message>
- <message>
- <location line="+6"/>
+ <location filename="../sendcoinsdialog.cpp" line="-170"/>
<source>Confirm send coins</source>
<translation>Confirm send coins</translation>
</message>
<message>
- <location line="+1"/>
- <source>Are you sure you want to send %1?</source>
- <translation>Are you sure you want to send %1?</translation>
+ <location line="-97"/>
+ <source>to</source>
+ <translation type="unfinished">to</translation>
</message>
<message>
- <location line="+0"/>
- <source> and </source>
- <translation> and </translation>
+ <location line="+15"/>
+ <source>&lt;b&gt;%1&lt;/b&gt; to %2</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+23"/>
@@ -1512,36 +1551,63 @@ Address: %4
<translation>Error: Transaction creation failed!</translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+15"/>
+ <source>Are you sure you want to send?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>added as transaction fee</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Total Amount %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+20"/>
<source>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source>
<translation>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</translation>
</message>
+ <message>
+ <location line="+145"/>
+ <source>Payment request expired</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Invalid payment address %1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
<message>
- <location filename="../forms/sendcoinsentry.ui" line="+14"/>
+ <location filename="../forms/sendcoinsentry.ui" line="+24"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location line="+15"/>
+ <location line="+588"/>
<source>A&amp;mount:</source>
<translation>A&amp;mount:</translation>
</message>
<message>
- <location line="+13"/>
+ <location line="-575"/>
+ <location line="+588"/>
<source>Pay &amp;To:</source>
<translation>Pay &amp;To:</translation>
</message>
<message>
- <location line="+34"/>
+ <location line="-554"/>
<source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
<translation>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
</message>
<message>
<location line="+60"/>
- <location filename="../sendcoinsentry.cpp" line="+26"/>
+ <location filename="../sendcoinsentry.cpp" line="+28"/>
<source>Enter a label for this address to add it to your address book</source>
<translation>Enter a label for this address to add it to your address book</translation>
</message>
@@ -1551,7 +1617,12 @@ Address: %4
<translation>&amp;Label:</translation>
</message>
<message>
- <location line="+28"/>
+ <location line="-54"/>
+ <source>StackedWidget</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+82"/>
<source>Choose address from address book</source>
<translation>Choose address from address book</translation>
</message>
@@ -1576,6 +1647,21 @@ Address: %4
<translation>Remove this recipient</translation>
</message>
<message>
+ <location line="+466"/>
+ <source>SecureSend</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Memo:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+63"/>
+ <source>message from merchant</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../sendcoinsentry.cpp" line="+1"/>
<source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
<translation>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
@@ -1708,7 +1794,7 @@ Address: %4
<translation>Enter Bitcoin signature</translation>
</message>
<message>
- <location line="+82"/>
+ <location line="+85"/>
<location line="+81"/>
<source>The entered address is invalid.</source>
<translation>The entered address is invalid.</translation>
@@ -1777,7 +1863,7 @@ Address: %4
<context>
<name>SplashScreen</name>
<message>
- <location filename="../splashscreen.cpp" line="+22"/>
+ <location filename="../splashscreen.cpp" line="+23"/>
<source>The Bitcoin developers</source>
<translation>The Bitcoin developers</translation>
</message>
@@ -1790,7 +1876,7 @@ Address: %4
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="+20"/>
+ <location filename="../transactiondesc.cpp" line="+22"/>
<source>Open until %1</source>
<translation>Open until %1</translation>
</message>
@@ -1866,12 +1952,12 @@ Address: %4
<location line="+12"/>
<location line="+45"/>
<location line="+17"/>
- <location line="+30"/>
+ <location line="+45"/>
<source>Credit</source>
<translation>Credit</translation>
</message>
<message numerus="yes">
- <location line="-102"/>
+ <location line="-117"/>
<source>matures in %n more block(s)</source>
<translation>
<numerusform>matures in %n more block</numerusform>
@@ -1887,12 +1973,12 @@ Address: %4
<location line="+44"/>
<location line="+8"/>
<location line="+15"/>
- <location line="+30"/>
+ <location line="+45"/>
<source>Debit</source>
<translation>Debit</translation>
</message>
<message>
- <location line="-39"/>
+ <location line="-54"/>
<source>Transaction fee</source>
<translation>Transaction fee</translation>
</message>
@@ -1917,7 +2003,12 @@ Address: %4
<translation>Transaction ID</translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+13"/>
+ <source>Merchant</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
<source>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
<translation>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</translation>
</message>
@@ -1952,7 +2043,7 @@ Address: %4
<translation>false</translation>
</message>
<message>
- <location line="-209"/>
+ <location line="-224"/>
<source>, has not been successfully broadcast yet</source>
<translation>, has not been successfully broadcast yet</translation>
</message>
@@ -1986,7 +2077,7 @@ Address: %4
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+225"/>
+ <location filename="../transactiontablemodel.cpp" line="+227"/>
<source>Date</source>
<translation>Date</translation>
</message>
@@ -2279,7 +2370,7 @@ Address: %4
<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="+193"/>
+ <location filename="../walletmodel.cpp" line="+218"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -2297,7 +2388,7 @@ Address: %4
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+197"/>
+ <location line="+198"/>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index d1fe37fea5..6c9a46bcf7 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -1,6 +1,10 @@
#ifndef NOTIFICATOR_H
#define NOTIFICATOR_H
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include <QObject>
#include <QIcon>
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index b2451aea31..7ccda6cdd4 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -1,3 +1,7 @@
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "optionsdialog.h"
#include "ui_optionsdialog.h"
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index d93a60e1bc..95efc58320 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -1,3 +1,7 @@
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "optionsmodel.h"
#include "bitcoinunits.h"
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index 289ddabb92..f6a898ff7c 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -24,18 +24,18 @@ bool PaymentRequestPlus::parse(const QByteArray& data)
{
bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size());
if (!parseOK) {
- qDebug() << "Error parsing payment request";
+ qDebug() << "PaymentRequestPlus::parse : Error parsing payment request";
return false;
}
if (paymentRequest.payment_details_version() > 1) {
- qDebug() << "Received up-version payment details, version=" << paymentRequest.payment_details_version();
+ qDebug() << "PaymentRequestPlus::parse : Received up-version payment details, version=" << paymentRequest.payment_details_version();
return false;
}
parseOK = details.ParseFromString(paymentRequest.serialized_payment_details());
if (!parseOK)
{
- qDebug() << "Error parsing payment details";
+ qDebug() << "PaymentRequestPlus::parse : Error parsing payment details";
paymentRequest.Clear();
return false;
}
@@ -75,17 +75,18 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
digestAlgorithm = EVP_sha1();
}
else if (paymentRequest.pki_type() == "none") {
- if (fDebug) qDebug() << "PaymentRequest: pki_type == none";
+ if (fDebug)
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none";
return false;
}
else {
- qDebug() << "PaymentRequest: unknown pki_type " << paymentRequest.pki_type().c_str();
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
return false;
}
payments::X509Certificates certChain;
if (!certChain.ParseFromString(paymentRequest.pki_data())) {
- qDebug() << "PaymentRequest: error parsing pki_data";
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data";
return false;
}
@@ -95,12 +96,12 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
QSslCertificate qCert(certData, QSsl::Der);
if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
- qDebug() << "PaymentRequest: certificate expired or not yet active: " << qCert;
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert;
return false;
}
#if QT_VERSION >= 0x050000
if (qCert.isBlacklisted()) {
- qDebug() << "PaymentRequest: certificate blacklisted: " << qCert;
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert;
return false;
}
#endif
@@ -110,7 +111,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
certs.push_back(cert);
}
if (certs.empty()) {
- qDebug() << "PaymentRequest: empty certificate chain";
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain";
return false;
}
@@ -126,7 +127,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
// load the signing cert into it and verify.
X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
if (!store_ctx) {
- qDebug() << "PaymentRequest: error creating X509_STORE_CTX";
+ qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX";
return false;
}
@@ -151,7 +152,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
// Valid cert; check signature:
payments::PaymentRequest rcopy(paymentRequest); // Copy
rcopy.set_signature(std::string(""));
- std::string data_to_verify; // Everything but the signature
+ std::string data_to_verify; // Everything but the signature
rcopy.SerializeToString(&data_to_verify);
EVP_MD_CTX ctx;
@@ -171,14 +172,14 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
merchant = website;
}
else {
- throw SSLVerifyError("Bad certificate, missing common name");
+ throw SSLVerifyError("Bad certificate, missing common name.");
}
// TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
}
catch (SSLVerifyError& err)
{
fResult = false;
- qDebug() << "PaymentRequestPlus::getMerchant SSL err: " << err.what();
+ qDebug() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what();
}
if (website)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index ff3c2a0981..96ba997943 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -44,10 +44,11 @@
#include "wallet.h"
#include "walletmodel.h"
-using namespace boost;
-
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("bitcoin:");
+const char* BITCOIN_REQUEST_MIMETYPE = "application/bitcoin-paymentrequest";
+const char* BITCOIN_PAYMENTACK_MIMETYPE = "application/bitcoin-paymentack";
+const char* BITCOIN_PAYMENTACK_CONTENTTYPE = "application/bitcoin-payment";
X509_STORE* PaymentServer::certStore = NULL;
void PaymentServer::freeCertStore()
@@ -71,14 +72,14 @@ static QString ipcServerName()
// Append a simple hash of the datadir
// Note that GetDataDir(true) returns a different path
// for -testnet versus main net
- QString ddir(GetDataDir(true).string().c_str());
+ QString ddir(QString::fromStdString(GetDataDir(true).string()));
name.append(QString::number(qHash(ddir)));
return name;
}
//
-// We store payment URLs and requests received before
+// We store payment URIs and requests received before
// the main GUI window is up and ready to ask the user
// to send payment.
@@ -87,12 +88,12 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
if (fDebug) {
- qDebug() << "Invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
+ qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
}
}
//
-// Load openSSL's list of root certificate authorities
+// Load OpenSSL's list of root certificate authorities
//
void PaymentServer::LoadRootCAs(X509_STORE* _store)
{
@@ -147,7 +148,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
const unsigned char *data = (const unsigned char *)certData.data();
X509* x509 = d2i_X509(0, &data, certData.size());
- if (x509 && X509_STORE_add_cert( PaymentServer::certStore, x509))
+ if (x509 && X509_STORE_add_cert(PaymentServer::certStore, x509))
{
// Note: X509_STORE_free will free the X509* objects when
// the PaymentServer is destroyed
@@ -160,7 +161,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
}
}
if (fDebug)
- qDebug() << "PaymentServer: loaded " << nRootCerts << " root certificates";
+ qDebug() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates";
// Project for another day:
// Fetch certificate revocation lists, and add them to certStore.
@@ -219,7 +220,7 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[])
}
else
{
- qDebug() << "Payment request file does not exist: " << argv[i];
+ qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << argv[i];
// Printing to debug.log is about the best we can do here, the
// GUI hasn't started yet so we can't pop up a message box.
}
@@ -248,8 +249,7 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[])
return fResult;
}
-PaymentServer::PaymentServer(QObject* parent,
- bool startLocalServer) : QObject(parent), saveURIs(true)
+PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : QObject(parent), saveURIs(true)
{
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
@@ -269,7 +269,7 @@ PaymentServer::PaymentServer(QObject* parent,
uriServer = new QLocalServer(this);
if (!uriServer->listen(name))
- qDebug() << "Cannot start bitcoin: click-to-pay handler";
+ qDebug() << "PaymentServer::PaymentServer : Cannot start bitcoin: click-to-pay handler";
else
connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection()));
}
@@ -284,12 +284,12 @@ PaymentServer::~PaymentServer()
}
//
-// OSX-specific way of handling bitcoin uris and
+// OSX-specific way of handling bitcoin: URIs and
// PaymentRequest mime types
//
bool PaymentServer::eventFilter(QObject *, QEvent *event)
{
- // clicking on bitcoin: URLs creates FileOpen events on the Mac:
+ // clicking on bitcoin: URIs creates FileOpen events on the Mac:
if (event->type() == QEvent::FileOpen)
{
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
@@ -303,18 +303,20 @@ bool PaymentServer::eventFilter(QObject *, QEvent *event)
return false;
}
-void PaymentServer::initNetManager(const OptionsModel& options)
+void PaymentServer::initNetManager()
{
+ if (!optionsModel)
+ return;
if (netManager != NULL)
delete netManager;
// netManager is used to fetch paymentrequests given in bitcoin: URI's
netManager = new QNetworkAccessManager(this);
- // Use proxy settings from options:
+ // Use proxy settings from optionsModel:
QString proxyIP;
quint16 proxyPort;
- if (options.getProxySettings(proxyIP, proxyPort))
+ if (optionsModel->getProxySettings(proxyIP, proxyPort))
{
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::Socks5Proxy);
@@ -352,22 +354,23 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin:
{
#if QT_VERSION >= 0x050000
- QUrlQuery url((QUrl(s)));
+ QUrlQuery uri((QUrl(s)));
#else
- QUrl url(s);
+ QUrl uri(s);
#endif
- if (url.hasQueryItem("request"))
+ if (uri.hasQueryItem("request"))
{
- QByteArray temp; temp.append(url.queryItemValue("request"));
+ QByteArray temp; temp.append(uri.queryItemValue("request"));
QString decoded = QUrl::fromPercentEncoding(temp);
QUrl fetchUrl(decoded, QUrl::StrictMode);
- if (fDebug) qDebug() << "PaymentServer::fetchRequest " << fetchUrl;
+ if (fDebug)
+ qDebug() << "PaymentServer::handleURIOrFile : fetchRequest(" << fetchUrl << ")";
if (fetchUrl.isValid())
fetchRequest(fetchUrl);
else
- qDebug() << "PaymentServer: invalid url: " << fetchUrl;
+ qDebug() << "PaymentServer::handleURIOrFile : Invalid url: " << fetchUrl;
return;
}
@@ -416,13 +419,13 @@ bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPl
QFile f(filename);
if (!f.open(QIODevice::ReadOnly))
{
- qDebug() << "PaymentServer::readPaymentRequest fail to open " << filename;
+ qDebug() << "PaymentServer::readPaymentRequest : Failed to open " << filename;
return false;
}
if (f.size() > MAX_PAYMENT_REQUEST_SIZE)
{
- qDebug() << "PaymentServer::readPaymentRequest " << filename << " too large";
+ qDebug() << "PaymentServer::readPaymentRequest : " << filename << " too large";
return false;
}
@@ -431,18 +434,20 @@ bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPl
return request.parse(data);
}
-bool
-PaymentServer::processPaymentRequest(PaymentRequestPlus& request,
- QList<SendCoinsRecipient>& recipients)
+bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<SendCoinsRecipient>& recipients)
{
+ if (!optionsModel)
+ return false;
+
QList<std::pair<CScript,qint64> > sendingTos = request.getPayTo();
qint64 totalAmount = 0;
foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) {
CTxOut txOut(sendingTo.second, sendingTo.first);
if (txOut.IsDust(CTransaction::nMinRelayTxFee)) {
QString message = QObject::tr("Requested payment amount (%1) too small")
- .arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendingTo.second));
- qDebug() << message;
+ .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second));
+
+ qDebug() << "PaymentServer::processPaymentRequest : " << message;
emit reportError(tr("Payment request error"), message, CClientUIInterface::MODAL);
return false;
}
@@ -455,7 +460,8 @@ PaymentServer::processPaymentRequest(PaymentRequestPlus& request,
if (request.getMerchant(PaymentServer::certStore, recipients[0].authenticatedMerchant)) {
recipients[0].paymentRequest = request;
recipients[0].amount = totalAmount;
- if (fDebug) qDebug() << "PaymentRequest from " << recipients[0].authenticatedMerchant;
+ if (fDebug)
+ qDebug() << "PaymentServer::processPaymentRequest : Payment request from " << recipients[0].authenticatedMerchant;
}
else {
recipients.clear();
@@ -466,23 +472,20 @@ PaymentServer::processPaymentRequest(PaymentRequestPlus& request,
recipients.append(SendCoinsRecipient());
recipients[i].amount = sendingTo.second;
QString memo = QString::fromStdString(request.getDetails().memo());
-#if QT_VERSION < 0x050000
- recipients[i].label = Qt::escape(memo);
-#else
- recipients[i].label = memo.toHtmlEscaped();
-#endif
+ recipients[i].label = GUIUtil::HtmlEscape(memo);
CTxDestination dest;
if (ExtractDestination(sendingTo.first, dest)) {
if (i == 0) // Tie request to first pay-to, we don't want multiple ACKs
recipients[i].paymentRequest = request;
recipients[i].address = QString::fromStdString(CBitcoinAddress(dest).ToString());
- if (fDebug) qDebug() << "PaymentRequest, insecure " << recipients[i].address;
+ if (fDebug)
+ qDebug() << "PaymentServer::processPaymentRequest : Payment request, insecure " << recipients[i].address;
}
else {
// Insecure payments to custom bitcoin addresses are not supported
// (there is no good way to tell the user where they are paying in a way
// they'd have a chance of understanding).
- emit reportError(tr("Payment request error"),
+ emit reportError(tr("Payment request error"),
tr("Insecure requests to custom payment scripts unsupported"),
CClientUIInterface::MODAL);
return false;
@@ -493,18 +496,17 @@ PaymentServer::processPaymentRequest(PaymentRequestPlus& request,
return true;
}
-void
-PaymentServer::fetchRequest(const QUrl& url)
+void PaymentServer::fetchRequest(const QUrl& url)
{
QNetworkRequest netRequest;
netRequest.setAttribute(QNetworkRequest::User, "PaymentRequest");
netRequest.setUrl(url);
netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
+ netRequest.setRawHeader("Accept", BITCOIN_REQUEST_MIMETYPE);
netManager->get(netRequest);
}
-void
-PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction)
+void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction)
{
const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();
if (!details.has_payment_url())
@@ -513,8 +515,9 @@ PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipient, QB
QNetworkRequest netRequest;
netRequest.setAttribute(QNetworkRequest::User, "PaymentACK");
netRequest.setUrl(QString::fromStdString(details.payment_url()));
- netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/bitcoin-payment");
+ netRequest.setHeader(QNetworkRequest::ContentTypeHeader, BITCOIN_PAYMENTACK_CONTENTTYPE);
netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
+ netRequest.setRawHeader("Accept", BITCOIN_PAYMENTACK_MIMETYPE);
payments::Payment payment;
payment.set_merchant_data(details.merchant_data());
@@ -542,7 +545,7 @@ PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipient, QB
else {
// This should never happen, because sending coins should have just unlocked the wallet
// and refilled the keypool
- qDebug() << "Error getting refund key, refund_to not set";
+ qDebug() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set";
}
}
@@ -554,12 +557,11 @@ PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipient, QB
}
else {
// This should never happen, either:
- qDebug() << "Error serializing payment message";
+ qDebug() << "PaymentServer::fetchPaymentACK : Error serializing payment message";
}
}
-void
-PaymentServer::netRequestFinished(QNetworkReply* reply)
+void PaymentServer::netRequestFinished(QNetworkReply* reply)
{
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError)
@@ -567,7 +569,7 @@ PaymentServer::netRequestFinished(QNetworkReply* reply)
QString message = QObject::tr("Error communicating with %1: %2")
.arg(reply->request().url().toString())
.arg(reply->errorString());
- qDebug() << message;
+ qDebug() << "PaymentServer::netRequestFinished : " << message;
emit reportError(tr("Network request error"), message, CClientUIInterface::MODAL);
return;
}
@@ -585,7 +587,7 @@ PaymentServer::netRequestFinished(QNetworkReply* reply)
}
}
else
- qDebug() << "PaymentServer::netRequestFinished: error processing PaymentRequest";
+ qDebug() << "PaymentServer::netRequestFinished : Error processing payment request";
return;
}
else if (requestType == "PaymentACK")
@@ -595,7 +597,7 @@ PaymentServer::netRequestFinished(QNetworkReply* reply)
{
QString message = QObject::tr("Bad response from server %1")
.arg(reply->request().url().toString());
- qDebug() << message;
+ qDebug() << "PaymentServer::netRequestFinished : " << message;
emit reportError(tr("Network request error"), message, CClientUIInterface::MODAL);
}
else {
@@ -604,13 +606,19 @@ PaymentServer::netRequestFinished(QNetworkReply* reply)
}
}
-void
-PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> &errs)
+void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> &errs)
{
+ Q_UNUSED(reply);
+
QString errString;
foreach (const QSslError& err, errs) {
- qDebug() << err;
+ qDebug() << "PaymentServer::reportSslErrors : " << err;
errString += err.errorString() + "\n";
}
emit reportError(tr("Network request error"), errString, CClientUIInterface::MODAL);
}
+
+void PaymentServer::setOptionsModel(OptionsModel *optionsModel)
+{
+ this->optionsModel = optionsModel;
+}
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index 7c6b2eabf0..f9d827204b 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -17,7 +17,7 @@
// received at or during startup in a list.
//
// When startup is finished and the main window is
-// show, a signal is sent to slot uiReady(), which
+// shown, a signal is sent to slot uiReady(), which
// emits a receivedURL() signal for any payment
// requests that happened during startup.
//
@@ -36,6 +36,8 @@
class CWallet;
class OptionsModel;
+
+QT_BEGIN_NAMESPACE
class QApplication;
class QByteArray;
class QLocalServer;
@@ -43,6 +45,7 @@ class QNetworkAccessManager;
class QNetworkReply;
class QSslError;
class QUrl;
+QT_END_NAMESPACE
class PaymentServer : public QObject
{
@@ -56,8 +59,8 @@ public:
// will be called so we startup in the right mode.
static bool ipcSendCommandLine(int argc, char *argv[]);
- PaymentServer(QObject* parent, // parent should be QApplication object
- bool startLocalServer=true);
+ // parent should be QApplication object
+ PaymentServer(QObject* parent, bool startLocalServer = true);
~PaymentServer();
// Load root certificate authorities. Pass NULL (default)
@@ -65,18 +68,21 @@ public:
// or, if that's not set, to use the system default root certificates.
// If you pass in a store, you should not X509_STORE_free it: it will be
// freed either at exit or when another set of CAs are loaded.
- static void LoadRootCAs(X509_STORE* store=NULL);
+ static void LoadRootCAs(X509_STORE* store = NULL);
// Return certificate store
static X509_STORE* getCertStore() { return certStore; }
- // Setup networking (options is used to get proxy settings)
- void initNetManager(const OptionsModel& options);
+ // Setup networking
+ void initNetManager();
// Constructor registers this on the parent QApplication to
// receive QEvent::FileOpen events
bool eventFilter(QObject *object, QEvent *event);
+ // OptionsModel is used for getting proxy settings and display unit
+ void setOptionsModel(OptionsModel *optionsModel);
+
signals:
// Fired when a valid payment request is received
void receivedPaymentRequest(SendCoinsRecipient);
@@ -106,12 +112,15 @@ private:
void handleURIOrFile(const QString& s);
void fetchRequest(const QUrl& url);
- bool saveURIs; // true during startup
+ bool saveURIs; // true during startup
QLocalServer* uriServer;
- static X509_STORE* certStore; // Trusted root certificates
+
+ static X509_STORE* certStore; // Trusted root certificates
static void freeCertStore();
- QNetworkAccessManager* netManager; // Used to fetch payment requests
+ QNetworkAccessManager* netManager; // Used to fetch payment requests
+
+ OptionsModel *optionsModel;
};
#endif // PAYMENTSERVER_H
diff --git a/src/qt/res/bitcoin-qt.rc b/src/qt/res/bitcoin-qt-res.rc
index 3e3672a835..3e3672a835 100644
--- a/src/qt/res/bitcoin-qt.rc
+++ b/src/qt/res/bitcoin-qt-res.rc
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 8953c36579..e7dcdf62a1 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -22,6 +22,8 @@
const int CONSOLE_HISTORY = 50;
const QSize ICON_SIZE(24, 24);
+const int INITIAL_TRAFFIC_GRAPH_MINS = 30;
+
const struct {
const char *url;
const char *source;
@@ -204,6 +206,7 @@ RPCConsole::RPCConsole(QWidget *parent) :
ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
startExecutor();
+ setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
clear();
}
@@ -253,7 +256,8 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
void RPCConsole::setClientModel(ClientModel *model)
{
- this->clientModel = model;
+ clientModel = model;
+ ui->trafficGraph->setClientModel(model);
if(model)
{
// Keep up to date with client
@@ -263,6 +267,9 @@ void RPCConsole::setClientModel(ClientModel *model)
setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
+ updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
+ connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
+
// Provide initial values
ui->clientVersion->setText(model->formatFullVersion());
ui->clientName->setText(model->clientName());
@@ -431,3 +438,49 @@ void RPCConsole::on_showCLOptionsButton_clicked()
GUIUtil::HelpMessageBox help;
help.exec();
}
+
+void RPCConsole::on_sldGraphRange_valueChanged(int value)
+{
+ const int multiplier = 5; // each position on the slider represents 5 min
+ int mins = value * multiplier;
+ setTrafficGraphRange(mins);
+}
+
+QString RPCConsole::FormatBytes(quint64 bytes)
+{
+ if(bytes < 1024)
+ return QString(tr("%1 B")).arg(bytes);
+ if(bytes < 1024 * 1024)
+ return QString(tr("%1 KB")).arg(bytes / 1024);
+ if(bytes < 1024 * 1024 * 1024)
+ return QString(tr("%1 MB")).arg(bytes / 1024 / 1024);
+
+ return QString(tr("%1 GB")).arg(bytes / 1024 / 1024 / 1024);
+}
+
+void RPCConsole::setTrafficGraphRange(int mins)
+{
+ ui->trafficGraph->setGraphRangeMins(mins);
+ if(mins < 60) {
+ ui->lblGraphRange->setText(QString(tr("%1 m")).arg(mins));
+ } else {
+ int hours = mins / 60;
+ int minsLeft = mins % 60;
+ if(minsLeft == 0) {
+ ui->lblGraphRange->setText(QString(tr("%1 h")).arg(hours));
+ } else {
+ ui->lblGraphRange->setText(QString(tr("%1 h %2 m")).arg(hours).arg(minsLeft));
+ }
+ }
+}
+
+void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
+{
+ ui->lblBytesIn->setText(FormatBytes(totalBytesIn));
+ ui->lblBytesOut->setText(FormatBytes(totalBytesOut));
+}
+
+void RPCConsole::on_btnClearTrafficGraph_clicked()
+{
+ ui->trafficGraph->clear();
+}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 3c38b4b8de..af92b55770 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -37,6 +37,12 @@ private slots:
void on_openDebugLogfileButton_clicked();
/** display messagebox with program parameters (same as bitcoin-qt --help) */
void on_showCLOptionsButton_clicked();
+ /** change the time range of the network traffic graph */
+ void on_sldGraphRange_valueChanged(int value);
+ /** update traffic statistics */
+ void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut);
+ /** clear traffic graph */
+ void on_btnClearTrafficGraph_clicked();
public slots:
void clear();
@@ -55,6 +61,9 @@ signals:
void cmdRequest(const QString &command);
private:
+ static QString FormatBytes(quint64 bytes);
+ void setTrafficGraphRange(int mins);
+
Ui::RPCConsole *ui;
ClientModel *clientModel;
QStringList history;
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 9086f6614e..3fd4a26e76 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -63,12 +63,12 @@ SendCoinsDialog::~SendCoinsDialog()
void SendCoinsDialog::on_sendButton_clicked()
{
+ if(!model || !model->getOptionsModel())
+ return;
+
QList<SendCoinsRecipient> recipients;
bool valid = true;
- if(!model)
- return;
-
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
@@ -94,40 +94,37 @@ void SendCoinsDialog::on_sendButton_clicked()
QStringList formatted;
foreach(const SendCoinsRecipient &rcp, recipients)
{
- QString amount = BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount);
+ // generate bold amount string
+ QString amount = "<b>" + BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
+ amount.append("</b>");
+ // generate monospace address string
+ QString address = "<span style='font-family: monospace;'>" + rcp.address;
+ address.append("</span>");
+
+ QString recipientElement;
+
if (rcp.authenticatedMerchant.isEmpty())
{
- QString address = rcp.address;
-#if QT_VERSION < 0x050000
- QString to = Qt::escape(rcp.label);
-#else
- QString to = rcp.label.toHtmlEscaped();
-#endif
- formatted.append(tr("<b>%1</b> to %2 (%3)").arg(amount, to, address));
+ if(rcp.label.length() > 0) // label with address
+ {
+ recipientElement = tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.label));
+ recipientElement.append(QString(" (%1)").arg(address));
+ }
+ else // just address
+ {
+ recipientElement = tr("%1 to %2").arg(amount, address);
+ }
}
- else
+ else // just merchant
{
-#if QT_VERSION < 0x050000
- QString merchant = Qt::escape(rcp.authenticatedMerchant);
-#else
- QString merchant = rcp.authenticatedMerchant.toHtmlEscaped();
-#endif
- formatted.append(tr("<b>%1</b> to %2").arg(amount, merchant));
+ recipientElement = tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant));
}
+
+ formatted.append(recipientElement);
}
fNewRecipientAllowed = false;
- QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
- tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
- QMessageBox::Yes|QMessageBox::Cancel,
- QMessageBox::Cancel);
-
- if(retval != QMessageBox::Yes)
- {
- fNewRecipientAllowed = true;
- return;
- }
WalletModel::UnlockContext ctx(model->requestUnlock());
if(!ctx.isValid())
@@ -137,50 +134,94 @@ void SendCoinsDialog::on_sendButton_clicked()
return;
}
- WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
- switch(sendstatus.status)
+ // prepare transaction for getting txFee earlier
+ WalletModelTransaction currentTransaction(recipients);
+ WalletModel::SendCoinsReturn prepareStatus = model->prepareTransaction(currentTransaction);
+
+ QString strSendCoins = tr("Send Coins");
+ switch(prepareStatus.status)
{
case WalletModel::InvalidAddress:
- QMessageBox::warning(this, tr("Send Coins"),
- tr("The recipient address is not valid, please recheck."),
- QMessageBox::Ok, QMessageBox::Ok);
+ QMessageBox::warning(this, strSendCoins,
+ tr("The recipient address is not valid, please recheck."));
break;
case WalletModel::InvalidAmount:
- QMessageBox::warning(this, tr("Send Coins"),
- tr("The amount to pay must be larger than 0."),
- QMessageBox::Ok, QMessageBox::Ok);
+ QMessageBox::warning(this, strSendCoins,
+ tr("The amount to pay must be larger than 0."));
break;
case WalletModel::AmountExceedsBalance:
- QMessageBox::warning(this, tr("Send Coins"),
- tr("The amount exceeds your balance."),
- QMessageBox::Ok, QMessageBox::Ok);
+ QMessageBox::warning(this, strSendCoins,
+ tr("The amount exceeds your balance."));
break;
case WalletModel::AmountWithFeeExceedsBalance:
- QMessageBox::warning(this, tr("Send Coins"),
+ QMessageBox::warning(this, strSendCoins,
tr("The total exceeds your balance when the %1 transaction fee is included.").
- arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
- QMessageBox::Ok, QMessageBox::Ok);
+ arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee())));
break;
case WalletModel::DuplicateAddress:
- QMessageBox::warning(this, tr("Send Coins"),
- tr("Duplicate address found, can only send to each address once per send operation."),
- QMessageBox::Ok, QMessageBox::Ok);
+ QMessageBox::warning(this, strSendCoins,
+ tr("Duplicate address found, can only send to each address once per send operation."));
break;
case WalletModel::TransactionCreationFailed:
- QMessageBox::warning(this, tr("Send Coins"),
- tr("Error: Transaction creation failed!"),
- QMessageBox::Ok, QMessageBox::Ok);
+ QMessageBox::warning(this, strSendCoins,
+ tr("Error: Transaction creation failed!"));
break;
case WalletModel::TransactionCommitFailed:
- QMessageBox::warning(this, tr("Send Coins"),
- tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."),
- QMessageBox::Ok, QMessageBox::Ok);
- break;
+ case WalletModel::OK:
case WalletModel::Aborted: // User aborted, nothing to do
+ default:
+ break;
+ }
+
+ if(prepareStatus.status != WalletModel::OK) {
+ fNewRecipientAllowed = true;
+ return;
+ }
+
+ qint64 txFee = currentTransaction.getTransactionFee();
+ QString questionString = tr("Are you sure you want to send?");
+ questionString.append("<br /><br />%1");
+
+ if(txFee > 0)
+ {
+ // append fee string if a fee is required
+ questionString.append("<hr /><span style='color:#aa0000;'>");
+ questionString.append(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
+ questionString.append("</span> ");
+ questionString.append(tr("added as transaction fee"));
+ }
+ if(txFee > 0 || recipients.count() > 1)
+ {
+ // add total amount string if there are more then one recipients or a fee is required
+ questionString.append("<hr />");
+ questionString.append(tr("Total Amount %1").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTotalTransactionAmount()+txFee)));
+ }
+
+ QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
+ questionString.arg(formatted.join("<br />")),
+ QMessageBox::Yes | QMessageBox::Cancel,
+ QMessageBox::Cancel);
+
+ if(retval != QMessageBox::Yes)
+ {
+ fNewRecipientAllowed = true;
+ return;
+ }
+
+ // now send the prepared transaction
+ WalletModel::SendCoinsReturn sendstatus = model->sendCoins(currentTransaction);
+ switch(sendstatus.status)
+ {
+ case WalletModel::TransactionCommitFailed:
+ QMessageBox::warning(this, strSendCoins,
+ tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
break;
case WalletModel::OK:
accept();
break;
+ case WalletModel::Aborted: // User aborted, nothing to do
+ default:
+ break;
}
fNewRecipientAllowed = true;
}
@@ -310,22 +351,22 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv)
{
+ QString strSendCoins = tr("Send Coins");
if (!rv.authenticatedMerchant.isEmpty()) {
// Expired payment request?
const payments::PaymentDetails& details = rv.paymentRequest.getDetails();
if (details.has_expires() && (int64)details.expires() < GetTime())
{
- QMessageBox::warning(this, tr("Send Coins"),
- tr("Payment request expired"));
+ QMessageBox::warning(this, strSendCoins,
+ tr("Payment request expired"));
return false;
}
}
else {
CBitcoinAddress address(rv.address.toStdString());
if (!address.IsValid()) {
- QString strAddress(address.ToString().c_str());
- QMessageBox::warning(this, tr("Send Coins"),
- tr("Invalid payment address %1").arg(strAddress));
+ QMessageBox::warning(this, strSendCoins,
+ tr("Invalid payment address %1").arg(rv.address));
return false;
}
}
@@ -338,18 +379,14 @@ void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint
{
Q_UNUSED(unconfirmedBalance);
Q_UNUSED(immatureBalance);
- if(!model || !model->getOptionsModel())
- return;
- int unit = model->getOptionsModel()->getDisplayUnit();
- ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
+ if(model && model->getOptionsModel())
+ {
+ ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), balance));
+ }
}
void SendCoinsDialog::updateDisplayUnit()
{
- if(model && model->getOptionsModel())
- {
- // Update labelBalance with the current balance and the current unit
- ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance()));
- }
+ setBalance(model->getBalance(), 0, 0);
}
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index e75a003ba1..f4bffedc9b 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -10,6 +10,7 @@ namespace Ui {
class WalletModel;
class SendCoinsEntry;
class SendCoinsRecipient;
+class OptionsModel;
QT_BEGIN_NAMESPACE
class QUrl;
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 75610f199e..aa671e0540 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -85,10 +85,17 @@ void SendCoinsEntry::setRemoveEnabled(bool enabled)
void SendCoinsEntry::clear()
{
+ // clear UI elements for insecure payments
ui->payTo->clear();
ui->addAsLabel->clear();
ui->payAmount->clear();
+ // and the ones for secure payments just to be sure
+ ui->payTo_s->clear();
+ ui->memoTextLabel_s->clear();
+ ui->payAmount_s->clear();
+
ui->payTo->setFocus();
+
// update the display unit, to not use the default ("BTC")
updateDisplayUnit();
}
@@ -106,8 +113,8 @@ bool SendCoinsEntry::validate()
if (!recipient.authenticatedMerchant.isEmpty())
return retval;
- if(!ui->payTo->hasAcceptableInput() ||
- (model && !model->validateAddress(ui->payTo->text())))
+ if (!ui->payTo->hasAcceptableInput() ||
+ (model && !model->validateAddress(ui->payTo->text())))
{
ui->payTo->setValid(false);
retval = false;
@@ -154,18 +161,20 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
recipient = value;
- ui->payTo->setText(value.address);
- ui->addAsLabel->setText(value.label);
- ui->payAmount->setValue(value.amount);
-
- if (!recipient.authenticatedMerchant.isEmpty())
+ if (recipient.authenticatedMerchant.isEmpty())
+ {
+ ui->payTo->setText(recipient.address);
+ ui->addAsLabel->setText(recipient.label);
+ ui->payAmount->setValue(recipient.amount);
+ }
+ else
{
- const payments::PaymentDetails& details = value.paymentRequest.getDetails();
+ const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();
- ui->payTo_s->setText(value.authenticatedMerchant);
- ui->memo_s->setTextFormat(Qt::PlainText);
- ui->memo_s->setText(QString::fromStdString(details.memo()));
- ui->payAmount_s->setValue(value.amount);
+ ui->payTo_s->setText(recipient.authenticatedMerchant);
+ ui->memoTextLabel_s->setText(QString::fromStdString(details.memo()));
+ ui->payAmount_s->setValue(recipient.amount);
+ ui->payAmount_s->setReadOnly(true);
setCurrentWidget(ui->SendCoinsSecure);
}
}
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index 9c7bfe9521..49e622daf1 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -33,7 +33,8 @@ public:
void setValue(const SendCoinsRecipient &value);
void setAddress(const QString &address);
- /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907).
+ /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases
+ * (issue https://bugreports.qt-project.org/browse/QTBUG-10907).
*/
QWidget *setupTabChain(QWidget *prev);
diff --git a/src/qt/test/Makefile.am b/src/qt/test/Makefile.am
new file mode 100644
index 0000000000..f8fe97462b
--- /dev/null
+++ b/src/qt/test/Makefile.am
@@ -0,0 +1,26 @@
+include $(top_srcdir)/src/Makefile.include
+
+AM_CPPFLAGS = $(INCLUDES) -I$(top_builddir)/src/obj \
+ -I$(top_srcdir)/src/leveldb/include -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/leveldb/helpers -I$(top_srcdir)/src/qt \
+ -I$(top_builddir)/src/qt $(BOOST_INCLUDES) $(PROTOBUF_CFLAGS) \
+ $(QR_CFLAGS) $(BDB_CPPFLAGS)
+AM_LDFLAGS = $(PTHREAD_CFLAGS)
+bin_PROGRAMS = test_bitcoin-qt
+TESTS = test_bitcoin-qt
+
+TEST_QT_MOC_CPP = moc_uritests.cpp moc_paymentservertests.cpp
+
+TEST_QT_H = uritests.h paymentservertests.h paymentrequestdata.h
+
+BUILT_SOURCES = $(TEST_QT_MOC_CPP)
+
+test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) $(QT_TEST_INCLUDES)
+test_bitcoin_qt_SOURCES = test_main.cpp uritests.cpp paymentservertests.cpp $(TEST_QT_H)
+nodist_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
+test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN) $(LIBLEVELDB) \
+ $(LIBMEMENV) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
+ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
+
+CLEANFILES = $(BUILT_SOURCES) *.gcda *.gcno
+
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
index 2e26ab0c9b..34079e94ff 100644
--- a/src/qt/test/paymentservertests.cpp
+++ b/src/qt/test/paymentservertests.cpp
@@ -2,6 +2,7 @@
#include <QDebug>
#include <QTemporaryFile>
#include <QVariant>
+#include <QFileOpenEvent>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
@@ -58,7 +59,8 @@ void PaymentServerTests::paymentServerTests()
X509_STORE* caStore = X509_STORE_new();
X509_STORE_add_cert(caStore, parse_b64der_cert(caCert_BASE64));
PaymentServer::LoadRootCAs(caStore);
- server->initNetManager(optionsModel);
+ server->setOptionsModel(&optionsModel);
+ server->initNetManager();
server->uiReady();
// Now feed PaymentRequests to server, and observe signals it produces:
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
new file mode 100644
index 0000000000..d49bc31f3e
--- /dev/null
+++ b/src/qt/trafficgraphwidget.cpp
@@ -0,0 +1,169 @@
+#include "trafficgraphwidget.h"
+#include "clientmodel.h"
+
+#include <QPainter>
+#include <QColor>
+#include <QTimer>
+
+#include <cmath>
+
+#define DESIRED_SAMPLES 800
+
+#define XMARGIN 10
+#define YMARGIN 10
+
+TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
+ QWidget(parent),
+ timer(0),
+ fMax(0.0f),
+ nMins(0),
+ vSamplesIn(),
+ vSamplesOut(),
+ nLastBytesIn(0),
+ nLastBytesOut(0),
+ clientModel(0)
+{
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
+}
+
+void TrafficGraphWidget::setClientModel(ClientModel *model)
+{
+ clientModel = model;
+ if(model) {
+ nLastBytesIn = model->getTotalBytesRecv();
+ nLastBytesOut = model->getTotalBytesSent();
+ }
+}
+
+int TrafficGraphWidget::getGraphRangeMins() const
+{
+ return nMins;
+}
+
+void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
+{
+ int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
+ int sampleCount = samples.size(), x = XMARGIN + w, y;
+ if(sampleCount > 0) {
+ path.moveTo(x, YMARGIN + h);
+ for(int i = 0; i < sampleCount; ++i) {
+ x = XMARGIN + w - w * i / DESIRED_SAMPLES;
+ y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
+ path.lineTo(x, y);
+ }
+ path.lineTo(x, YMARGIN + h);
+ }
+}
+
+void TrafficGraphWidget::paintEvent(QPaintEvent *)
+{
+ QPainter painter(this);
+ painter.fillRect(rect(), Qt::black);
+
+ if(fMax <= 0.0f) return;
+
+ QColor axisCol(Qt::gray);
+ int h = height() - YMARGIN * 2;
+ painter.setPen(axisCol);
+ painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);
+
+ // decide what order of magnitude we are
+ int base = floor(log10(fMax));
+ float val = pow(10.0f, base);
+
+ const QString units = tr("KB/s");
+ // draw lines
+ painter.setPen(axisCol);
+ painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units));
+ for(float y = val; y < fMax; y += val) {
+ int yy = YMARGIN + h - h * y / fMax;
+ painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
+ }
+ // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
+ if(fMax / val <= 3.0f) {
+ axisCol = axisCol.darker();
+ val = pow(10.0f, base - 1);
+ painter.setPen(axisCol);
+ painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units));
+ int count = 1;
+ for(float y = val; y < fMax; y += val, count++) {
+ // don't overwrite lines drawn above
+ if(count % 10 == 0)
+ continue;
+ int yy = YMARGIN + h - h * y / fMax;
+ painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
+ }
+ }
+
+ if(!vSamplesIn.empty()) {
+ QPainterPath p;
+ paintPath(p, vSamplesIn);
+ painter.fillPath(p, QColor(0, 255, 0, 128));
+ painter.setPen(Qt::green);
+ painter.drawPath(p);
+ }
+ if(!vSamplesOut.empty()) {
+ QPainterPath p;
+ paintPath(p, vSamplesOut);
+ painter.fillPath(p, QColor(255, 0, 0, 128));
+ painter.setPen(Qt::red);
+ painter.drawPath(p);
+ }
+}
+
+void TrafficGraphWidget::updateRates()
+{
+ if(!clientModel) return;
+
+ quint64 bytesIn = clientModel->getTotalBytesRecv(),
+ bytesOut = clientModel->getTotalBytesSent();
+ float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
+ float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
+ vSamplesIn.push_front(inRate);
+ vSamplesOut.push_front(outRate);
+ nLastBytesIn = bytesIn;
+ nLastBytesOut = bytesOut;
+
+ while(vSamplesIn.size() > DESIRED_SAMPLES) {
+ vSamplesIn.pop_back();
+ }
+ while(vSamplesOut.size() > DESIRED_SAMPLES) {
+ vSamplesOut.pop_back();
+ }
+
+ float tmax = 0.0f;
+ foreach(float f, vSamplesIn) {
+ if(f > tmax) tmax = f;
+ }
+ foreach(float f, vSamplesOut) {
+ if(f > tmax) tmax = f;
+ }
+ fMax = tmax;
+ update();
+}
+
+void TrafficGraphWidget::setGraphRangeMins(int mins)
+{
+ nMins = mins;
+ int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
+ timer->stop();
+ timer->setInterval(msecsPerSample);
+
+ clear();
+}
+
+void TrafficGraphWidget::clear()
+{
+ timer->stop();
+
+ vSamplesOut.clear();
+ vSamplesIn.clear();
+ fMax = 0.0f;
+
+ if(clientModel) {
+ nLastBytesIn = clientModel->getTotalBytesRecv();
+ nLastBytesOut = clientModel->getTotalBytesSent();
+ }
+ timer->start();
+}
diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h
new file mode 100644
index 0000000000..b31d1d5b0a
--- /dev/null
+++ b/src/qt/trafficgraphwidget.h
@@ -0,0 +1,44 @@
+#ifndef TRAFFICGRAPHWIDGET_H
+#define TRAFFICGRAPHWIDGET_H
+
+#include <QWidget>
+#include <QQueue>
+
+class ClientModel;
+
+QT_BEGIN_NAMESPACE
+class QPaintEvent;
+class QTimer;
+QT_END_NAMESPACE
+
+class TrafficGraphWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit TrafficGraphWidget(QWidget *parent = 0);
+ void setClientModel(ClientModel *model);
+ int getGraphRangeMins() const;
+
+protected:
+ void paintEvent(QPaintEvent *);
+
+public slots:
+ void updateRates();
+ void setGraphRangeMins(int mins);
+ void clear();
+
+private:
+ void paintPath(QPainterPath &path, QQueue<float> &samples);
+
+ QTimer *timer;
+ float fMax;
+ int nMins;
+ QQueue<float> vSamplesIn;
+ QQueue<float> vSamplesOut;
+ quint64 nLastBytesIn;
+ quint64 nLastBytesOut;
+ ClientModel *clientModel;
+};
+
+#endif // TRAFFICGRAPHWIDGET_H
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 25ff3623c0..93fc8cab22 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -8,6 +8,7 @@
#include "ui_interface.h"
#include "base58.h"
#include "paymentserver.h"
+#include "transactionrecord.h"
#include <string>
@@ -16,7 +17,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
if (!IsFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
- return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight + 1);
+ return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height() + 1);
else
return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
}
@@ -32,7 +33,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
}
}
-QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
+QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit)
{
QString strHTML;
@@ -129,7 +130,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
nUnmatured += wallet->GetCredit(txout);
strHTML += "<b>" + tr("Credit") + ":</b> ";
if (wtx.IsInMainChain())
- strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
+ strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
else
strHTML += "(" + tr("not accepted") + ")";
strHTML += "<br>";
@@ -139,7 +140,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
//
// Credit
//
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet) + "<br>";
}
else
{
@@ -175,7 +176,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
}
}
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>";
}
if (fAllToMe)
@@ -183,13 +184,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
// Payment to self
int64 nChange = wtx.GetChange();
int64 nValue = nCredit - nChange;
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nValue) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nValue) + "<br>";
}
int64 nTxFee = nDebit - GetValueOut(wtx);
if (nTxFee > 0)
- strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
+ strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nTxFee) + "<br>";
}
else
{
@@ -198,14 +199,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
//
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
if (wallet->IsMine(txin))
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "<br>";
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (wallet->IsMine(txout))
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "<br>";
}
}
- strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>";
+ strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet, true) + "<br>";
//
// Message
@@ -215,7 +216,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
- strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>";
+ strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), vout) + "<br>";
//
// PaymentRequest info:
@@ -225,7 +226,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
if (r.first == "PaymentRequest")
{
PaymentRequestPlus req;
- req.parse(QByteArray::fromRawData(r.second.c_str(), r.second.size()));
+ req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
QString merchant;
if (req.getMerchant(PaymentServer::getCertStore(), merchant))
strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
@@ -243,10 +244,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
if(wallet->IsMine(txin))
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "<br>";
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if(wallet->IsMine(txout))
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "<br>";
strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
@@ -274,7 +275,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
}
- strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue);
+ strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue);
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
}
}
diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h
index cb0dda5b58..8b3684e961 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -14,7 +14,7 @@ class TransactionDesc: public QObject
Q_OBJECT
public:
- static QString toHTML(CWallet *wallet, CWalletTx &wtx);
+ static QString toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit);
private:
TransactionDesc() {}
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index e954508769..162908a9a4 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -160,14 +160,14 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
idx);
status.confirmed = wtx.IsConfirmed();
status.depth = wtx.GetDepthInMainChain();
- status.cur_num_blocks = nBestHeight;
+ status.cur_num_blocks = chainActive.Height();
if (!IsFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
{
status.status = TransactionStatus::OpenUntilBlock;
- status.open_for = wtx.nLockTime - nBestHeight + 1;
+ status.open_for = wtx.nLockTime - chainActive.Height() + 1;
}
else
{
@@ -221,11 +221,16 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
bool TransactionRecord::statusUpdateNeeded()
{
- return status.cur_num_blocks != nBestHeight;
+ return status.cur_num_blocks != chainActive.Height();
}
-std::string TransactionRecord::getTxID()
+QString TransactionRecord::getTxID() const
{
- return hash.ToString() + strprintf("-%03d", idx);
+ return formatSubTxId(hash, idx);
+}
+
+QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout)
+{
+ return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout));
}
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index d760d47c89..480e7a7f2c 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -4,6 +4,7 @@
#include "uint256.h"
#include <QList>
+#include <QString>
class CWallet;
class CWalletTx;
@@ -117,7 +118,10 @@ public:
TransactionStatus status;
/** Return the unique identifier for this transaction (part) */
- std::string getTxID();
+ QString getTxID() const;
+
+ /** Format subtransaction id */
+ static QString formatSubTxId(const uint256 &hash, int vout);
/** Update status from core wallet tx.
*/
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index baf1e16483..6f7a5933ab 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -17,14 +17,15 @@
#include <QTimer>
#include <QIcon>
#include <QDateTime>
+#include <QDebug>
// Amount column is right-aligned it contains numbers
static int column_alignments[] = {
- Qt::AlignLeft|Qt::AlignVCenter,
- Qt::AlignLeft|Qt::AlignVCenter,
- Qt::AlignLeft|Qt::AlignVCenter,
- Qt::AlignLeft|Qt::AlignVCenter,
- Qt::AlignRight|Qt::AlignVCenter
+ Qt::AlignLeft|Qt::AlignVCenter, /* status */
+ Qt::AlignLeft|Qt::AlignVCenter, /* date */
+ Qt::AlignLeft|Qt::AlignVCenter, /* type */
+ Qt::AlignLeft|Qt::AlignVCenter, /* address */
+ Qt::AlignRight|Qt::AlignVCenter /* amount */
};
// Comparison operator for sort/binary search of model tx list
@@ -48,11 +49,12 @@ struct TxLessThan
class TransactionTablePriv
{
public:
- TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent):
- wallet(wallet),
- parent(parent)
+ TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent) :
+ wallet(wallet),
+ parent(parent)
{
}
+
CWallet *wallet;
TransactionTableModel *parent;
@@ -66,7 +68,7 @@ public:
*/
void refreshWallet()
{
- OutputDebugStringF("refreshWallet\n");
+ qDebug() << "TransactionTablePriv::refreshWallet";
cachedWallet.clear();
{
LOCK(wallet->cs_wallet);
@@ -85,7 +87,7 @@ public:
*/
void updateWallet(const uint256 &hash, int status)
{
- OutputDebugStringF("updateWallet %s %i\n", hash.ToString().c_str(), status);
+ qDebug() << "TransactionTablePriv::updateWallet : " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
{
LOCK(wallet->cs_wallet);
@@ -113,20 +115,21 @@ public:
status = CT_DELETED; /* In model, but want to hide, treat as deleted */
}
- OutputDebugStringF(" inWallet=%i inModel=%i Index=%i-%i showTransaction=%i derivedStatus=%i\n",
- inWallet, inModel, lowerIndex, upperIndex, showTransaction, status);
+ qDebug() << " inWallet=" + QString::number(inWallet) + " inModel=" + QString::number(inModel) +
+ " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
+ " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
switch(status)
{
case CT_NEW:
if(inModel)
{
- OutputDebugStringF("Warning: updateWallet: Got CT_NEW, but transaction is already in model\n");
+ qDebug() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is already in model";
break;
}
if(!inWallet)
{
- OutputDebugStringF("Warning: updateWallet: Got CT_NEW, but transaction is not in wallet\n");
+ qDebug() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is not in wallet";
break;
}
if(showTransaction)
@@ -150,7 +153,7 @@ public:
case CT_DELETED:
if(!inModel)
{
- OutputDebugStringF("Warning: updateWallet: Got CT_DELETED, but transaction is not in model\n");
+ qDebug() << "TransactionTablePriv::updateWallet : Warning: Got CT_DELETED, but transaction is not in model";
break;
}
// Removed -- remove entire transaction from table
@@ -200,19 +203,18 @@ public:
}
}
- QString describe(TransactionRecord *rec)
+ QString describe(TransactionRecord *rec, int unit)
{
{
LOCK(wallet->cs_wallet);
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end())
{
- return TransactionDesc::toHTML(wallet, mi->second);
+ return TransactionDesc::toHTML(wallet, mi->second, rec->idx, unit);
}
}
return QString("");
}
-
};
TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *parent):
@@ -248,9 +250,9 @@ void TransactionTableModel::updateTransaction(const QString &hash, int status)
void TransactionTableModel::updateConfirmations()
{
- if(nBestHeight != cachedNumBlocks)
+ if(chainActive.Height() != cachedNumBlocks)
{
- cachedNumBlocks = nBestHeight;
+ cachedNumBlocks = chainActive.Height();
// Blocks came in since last poll.
// Invalidate status (number of confirmations) and (possibly) description
// for all rows. Qt is smart enough to only actually request the data for the
@@ -561,7 +563,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case DateRole:
return QDateTime::fromTime_t(static_cast<uint>(rec->time));
case LongDescriptionRole:
- return priv->describe(rec);
+ return priv->describe(rec, walletModel->getOptionsModel()->getDisplayUnit());
case AddressRole:
return QString::fromStdString(rec->address);
case LabelRole:
@@ -569,7 +571,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case AmountRole:
return rec->credit + rec->debit;
case TxIDRole:
- return QString::fromStdString(rec->getTxID());
+ return rec->getTxID();
case ConfirmedRole:
// Return True if transaction counts for balance
return rec->status.confirmed && !(rec->type == TransactionRecord::Generated &&
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 99a6647a65..8d6a1b387e 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -56,12 +56,9 @@ bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
void WalletFrame::showOutOfSyncWarning(bool fShow)
{
- if (!walletStack) {
- QMessageBox box;
- box.setText("walletStack is null");
- box.exec();
+ if (!walletStack)
return;
- }
+
walletStack->showOutOfSyncWarning(fShow);
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 61357647b7..417bac9928 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -5,12 +5,12 @@
#include "transactiontablemodel.h"
#include "ui_interface.h"
-#include "wallet.h"
#include "walletdb.h" // for BackupWallet
#include "base58.h"
#include <QSet>
#include <QTimer>
+#include <QDebug>
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
@@ -73,10 +73,10 @@ void WalletModel::updateStatus()
void WalletModel::pollBalanceChanged()
{
- if(nBestHeight != cachedNumBlocks)
+ if(chainActive.Height() != cachedNumBlocks)
{
// Balance and number of transactions might have changed
- cachedNumBlocks = nBestHeight;
+ cachedNumBlocks = chainActive.Height();
checkBalanceChanged();
}
}
@@ -112,10 +112,11 @@ void WalletModel::updateTransaction(const QString &hash, int status)
}
}
-void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, int status)
+void WalletModel::updateAddressBook(const QString &address, const QString &label,
+ bool isMine, const QString &purpose, int status)
{
if(addressTableModel)
- addressTableModel->updateEntry(address, label, isMine, status);
+ addressTableModel->updateEntry(address, label, isMine, purpose, status);
}
bool WalletModel::validateAddress(const QString &address)
@@ -124,11 +125,11 @@ bool WalletModel::validateAddress(const QString &address)
return addressParsed.IsValid();
}
-WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipient> &recipients)
+WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction)
{
qint64 total = 0;
+ QList<SendCoinsRecipient> recipients = transaction.getRecipients();
std::vector<std::pair<CScript, int64> > vecSend;
- QByteArray transaction;
if(recipients.empty())
{
@@ -142,7 +143,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
foreach(const SendCoinsRecipient &rcp, recipients)
{
if (rcp.paymentRequest.IsInitialized())
- { // PaymentRequest...
+ { // PaymentRequest...
int64 subtotal = 0;
const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
for (int i = 0; i < details.outputs_size(); i++)
@@ -192,81 +193,97 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
if((total + nTransactionFee) > getBalance())
{
- return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee);
+ transaction.setTransactionFee(nTransactionFee);
+ return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
{
LOCK2(cs_main, wallet->cs_wallet);
- CReserveKey keyChange(wallet);
+ transaction.newPossibleKeyChange(wallet);
int64 nFeeRequired = 0;
std::string strFailReason;
- CWalletTx wtx;
- bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
+
+ CWalletTx *newTx = transaction.getTransaction();
+ CReserveKey *keyChange = transaction.getPossibleKeyChange();
+ bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason);
+ transaction.setTransactionFee(nFeeRequired);
if(!fCreated)
{
if((total + nFeeRequired) > wallet->GetBalance())
{
- return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired);
+ return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
emit message(tr("Send Coins"), QString::fromStdString(strFailReason),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
+ }
+
+ return SendCoinsReturn(OK);
+}
+
+WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction)
+{
+ QByteArray transaction_array; /* store serialized transaction */
+
+ {
+ LOCK2(cs_main, wallet->cs_wallet);
+ CWalletTx *newTx = transaction.getTransaction();
+
// Store PaymentRequests in wtx.vOrderForm in wallet.
- foreach(const SendCoinsRecipient &rcp, recipients)
+ foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
if (rcp.paymentRequest.IsInitialized())
{
std::string key("PaymentRequest");
std::string value;
rcp.paymentRequest.SerializeToString(&value);
- wtx.vOrderForm.push_back(make_pair(key, value));
+ newTx->vOrderForm.push_back(make_pair(key, value));
}
- }
-
- if(!uiInterface.ThreadSafeAskFee(nFeeRequired))
- {
- return Aborted;
}
- if(!wallet->CommitTransaction(wtx, keyChange))
- {
+
+ CReserveKey *keyChange = transaction.getPossibleKeyChange();
+ if(!wallet->CommitTransaction(*newTx, *keyChange))
return TransactionCommitFailed;
- }
- CTransaction* t = (CTransaction*)&wtx;
+ CTransaction* t = (CTransaction*)newTx;
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << *t;
- transaction.append(&(ssTx[0]), ssTx.size());
+ transaction_array.append(&(ssTx[0]), ssTx.size());
}
// Add addresses / update labels that we've sent to to the address book,
- // and emit coinsSent signal
- foreach(const SendCoinsRecipient &rcp, recipients)
+ // and emit coinsSent signal for each recipient
+ foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
- std::string strAddress = rcp.address.toStdString();
- CTxDestination dest = CBitcoinAddress(strAddress).Get();
- std::string strLabel = rcp.label.toStdString();
+ // Don't touch the address book when we have a secure payment-request
+ if (rcp.authenticatedMerchant.isEmpty())
{
- LOCK(wallet->cs_wallet);
-
- std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
-
- // Check if we have a new address or an updated label
- if (mi == wallet->mapAddressBook.end())
- {
- wallet->SetAddressBook(dest, strLabel, "send");
- }
- else if (mi->second.name != strLabel)
+ std::string strAddress = rcp.address.toStdString();
+ CTxDestination dest = CBitcoinAddress(strAddress).Get();
+ std::string strLabel = rcp.label.toStdString();
{
- wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ LOCK(wallet->cs_wallet);
+
+ std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
+
+ // Check if we have a new address or an updated label
+ if (mi == wallet->mapAddressBook.end())
+ {
+ wallet->SetAddressBook(dest, strLabel, "send");
+ }
+ else if (mi->second.name != strLabel)
+ {
+ wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ }
}
}
- emit coinsSent(wallet, rcp, transaction);
+ emit coinsSent(wallet, rcp, transaction_array);
}
- return SendCoinsReturn(OK, 0);
+ return SendCoinsReturn(OK);
}
OptionsModel *WalletModel::getOptionsModel()
@@ -347,25 +364,34 @@ bool WalletModel::backupWallet(const QString &filename)
// Handlers for core signals
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
{
- OutputDebugStringF("NotifyKeyStoreStatusChanged\n");
+ qDebug() << "NotifyKeyStoreStatusChanged";
QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
}
-static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status)
+static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
+ const CTxDestination &address, const std::string &label, bool isMine,
+ const std::string &purpose, ChangeType status)
{
- OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, status);
+ QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString());
+ QString strLabel = QString::fromStdString(label);
+ QString strPurpose = QString::fromStdString(purpose);
+
+ qDebug() << "NotifyAddressBookChanged : " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
- Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())),
- Q_ARG(QString, QString::fromStdString(label)),
+ Q_ARG(QString, strAddress),
+ Q_ARG(QString, strLabel),
Q_ARG(bool, isMine),
+ Q_ARG(QString, strPurpose),
Q_ARG(int, status));
}
static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
{
- OutputDebugStringF("NotifyTransactionChanged %s status=%i\n", hash.GetHex().c_str(), status);
+ QString strHash = QString::fromStdString(hash.GetHex());
+
+ qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection,
- Q_ARG(QString, QString::fromStdString(hash.GetHex())),
+ Q_ARG(QString, strHash),
Q_ARG(int, status));
}
@@ -373,7 +399,7 @@ void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
- wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
+ wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
}
@@ -381,7 +407,7 @@ void WalletModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from wallet
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
- wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
+ wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 8cba10f5d2..6abcdaf8cb 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -4,12 +4,15 @@
#include <QObject>
#include "allocators.h" /* for SecureString */
+#include "wallet.h"
+#include "walletmodeltransaction.h"
#include "paymentrequestplus.h"
class OptionsModel;
class AddressTableModel;
class TransactionTableModel;
class CWallet;
+class WalletModelTransaction;
QT_BEGIN_NAMESPACE
class QTimer;
@@ -74,15 +77,16 @@ public:
// Return status record for SendCoins, contains error id + information
struct SendCoinsReturn
{
- SendCoinsReturn(StatusCode status,
- qint64 fee=0):
- status(status), fee(fee) {}
+ SendCoinsReturn(StatusCode status):
+ status(status) {}
StatusCode status;
- qint64 fee; // is used in case status is "AmountWithFeeExceedsBalance"
};
+ // prepare transaction for getting txfee before sending coins
+ SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction);
+
// Send coins to a list of recipients
- SendCoinsReturn sendCoins(const QList<SendCoinsRecipient> &recipients);
+ SendCoinsReturn sendCoins(WalletModelTransaction &transaction);
// Wallet encryption
bool setWalletEncrypted(bool encrypted, const SecureString &passphrase);
@@ -165,7 +169,7 @@ public slots:
/* New transaction, or transaction changed status */
void updateTransaction(const QString &hash, int status);
/* New, updated or removed address book entry */
- void updateAddressBook(const QString &address, const QString &label, bool isMine, int status);
+ void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
void pollBalanceChanged();
};
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
new file mode 100644
index 0000000000..706ed60b77
--- /dev/null
+++ b/src/qt/walletmodeltransaction.cpp
@@ -0,0 +1,56 @@
+#include "walletmodeltransaction.h"
+
+WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &recipients) :
+ recipients(recipients),
+ walletTransaction(0),
+ keyChange(0),
+ fee(0)
+{
+ walletTransaction = new CWalletTx();
+}
+
+WalletModelTransaction::~WalletModelTransaction()
+{
+ delete keyChange;
+ delete walletTransaction;
+}
+
+QList<SendCoinsRecipient> WalletModelTransaction::getRecipients()
+{
+ return recipients;
+}
+
+CWalletTx *WalletModelTransaction::getTransaction()
+{
+ return walletTransaction;
+}
+
+qint64 WalletModelTransaction::getTransactionFee()
+{
+ return fee;
+}
+
+void WalletModelTransaction::setTransactionFee(qint64 newFee)
+{
+ fee = newFee;
+}
+
+qint64 WalletModelTransaction::getTotalTransactionAmount()
+{
+ qint64 totalTransactionAmount = 0;
+ foreach(const SendCoinsRecipient &rcp, recipients)
+ {
+ totalTransactionAmount += rcp.amount;
+ }
+ return totalTransactionAmount;
+}
+
+void WalletModelTransaction::newPossibleKeyChange(CWallet *wallet)
+{
+ keyChange = new CReserveKey(wallet);
+}
+
+CReserveKey *WalletModelTransaction::getPossibleKeyChange()
+{
+ return keyChange;
+}
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
new file mode 100644
index 0000000000..c4848fb12d
--- /dev/null
+++ b/src/qt/walletmodeltransaction.h
@@ -0,0 +1,37 @@
+#ifndef WALLETMODELTRANSACTION_H
+#define WALLETMODELTRANSACTION_H
+
+#include "walletmodel.h"
+
+class SendCoinsRecipient;
+
+/** Data model for a walletmodel transaction. */
+class WalletModelTransaction
+{
+public:
+ explicit WalletModelTransaction(const QList<SendCoinsRecipient> &recipients);
+ ~WalletModelTransaction();
+
+ QList<SendCoinsRecipient> getRecipients();
+
+ CWalletTx *getTransaction();
+
+ void setTransactionFee(qint64 newFee);
+ qint64 getTransactionFee();
+
+ qint64 getTotalTransactionAmount();
+
+ void newPossibleKeyChange(CWallet *wallet);
+ CReserveKey *getPossibleKeyChange();
+
+private:
+ const QList<SendCoinsRecipient> recipients;
+ CWalletTx *walletTransaction;
+ CReserveKey *keyChange;
+ qint64 fee;
+
+public slots:
+
+};
+
+#endif // WALLETMODELTRANSACTION_H
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index ba346f19d9..957241d6a0 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -9,7 +9,7 @@
using namespace json_spirit;
using namespace std;
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out);
+void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
double GetDifficulty(const CBlockIndex* blockindex)
{
@@ -17,10 +17,10 @@ double GetDifficulty(const CBlockIndex* blockindex)
// minimum difficulty = 1.0.
if (blockindex == NULL)
{
- if (pindexBest == NULL)
+ if (chainActive.Tip() == NULL)
return 1.0;
else
- blockindex = pindexBest;
+ blockindex = chainActive.Tip();
}
int nShift = (blockindex->nBits >> 24) & 0xff;
@@ -66,7 +66,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
- CBlockIndex *pnext = blockindex->GetNextInMainChain();
+ CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
return result;
@@ -80,7 +80,7 @@ Value getblockcount(const Array& params, bool fHelp)
"getblockcount\n"
"Returns the number of blocks in the longest block chain.");
- return nBestHeight;
+ return chainActive.Height();
}
Value getbestblockhash(const Array& params, bool fHelp)
@@ -90,7 +90,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
"getbestblockhash\n"
"Returns the hash of the best (tip) block in the longest block chain.");
- return hashBestChain.GetHex();
+ return chainActive.Tip()->GetBlockHash().GetHex();
}
Value getdifficulty(const Array& params, bool fHelp)
@@ -108,8 +108,8 @@ Value settxfee(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
- "settxfee <amount>\n"
- "<amount> is a real and is rounded to the nearest 0.00000001");
+ "settxfee <amount btc/kb>\n"
+ "<amount> is a real and is rounded to the nearest 0.00000001 btc per kb");
// Amount
int64 nAmount = 0;
@@ -145,11 +145,11 @@ Value getblockhash(const Array& params, bool fHelp)
"Returns hash of block in best-block-chain at <index>.");
int nHeight = params[0].get_int();
- if (nHeight < 0 || nHeight > nBestHeight)
+ if (nHeight < 0 || nHeight > chainActive.Height())
throw runtime_error("Block number out of range.");
- CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
- return pblockindex->phashBlock->GetHex();
+ CBlockIndex* pblockindex = chainActive[nHeight];
+ return pblockindex->GetBlockHash().GetHex();
}
Value getblock(const Array& params, bool fHelp)
@@ -245,7 +245,7 @@ Value gettxout(const Array& params, bool fHelp)
ret.push_back(Pair("confirmations", pcoinsTip->GetBestBlock()->nHeight - coins.nHeight + 1));
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
Object o;
- ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o);
+ ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
ret.push_back(Pair("scriptPubKey", o));
ret.push_back(Pair("version", coins.nVersion));
ret.push_back(Pair("coinbase", coins.fCoinBase));
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index e166f76bf1..61cd07d507 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -15,8 +15,6 @@
#include <boost/variant/get.hpp>
#include <boost/algorithm/string.hpp>
-#define printf OutputDebugStringF
-
using namespace json_spirit;
using namespace std;
@@ -104,7 +102,7 @@ Value importprivkey(const Array& params, bool fHelp)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
if (fRescan) {
- pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
+ pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ReacceptWalletTransactions();
}
}
@@ -126,7 +124,7 @@ Value importwallet(const Array& params, bool fHelp)
if (!file.is_open())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
- int64 nTimeBegin = pindexBest->nTime;
+ int64 nTimeBegin = chainActive.Tip()->nTime;
bool fGood = true;
@@ -147,7 +145,7 @@ Value importwallet(const Array& params, bool fHelp)
CPubKey pubkey = key.GetPubKey();
CKeyID keyid = pubkey.GetID();
if (pwalletMain->HaveKey(keyid)) {
- printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
+ LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
continue;
}
int64 nTime = DecodeDumpTime(vstr[1]);
@@ -165,7 +163,7 @@ Value importwallet(const Array& params, bool fHelp)
fLabel = true;
}
}
- printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
+ LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
@@ -177,11 +175,11 @@ Value importwallet(const Array& params, bool fHelp)
}
file.close();
- CBlockIndex *pindex = pindexBest;
+ CBlockIndex *pindex = chainActive.Tip();
while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
pindex = pindex->pprev;
- printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
+ LogPrintf("Rescanning last %i blocks\n", chainActive.Height() - pindex->nHeight + 1);
pwalletMain->ScanForWalletTransactions(pindex);
pwalletMain->ReacceptWalletTransactions();
pwalletMain->MarkDirty();
@@ -245,8 +243,8 @@ Value dumpwallet(const Array& params, bool fHelp)
// produce output
file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
- file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
- file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString().c_str());
+ file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->nTime).c_str());
file << "\n";
for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index c7f516caa7..f123c3a9e0 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -18,15 +18,71 @@ static CReserveKey* pMiningKey = NULL;
void InitRPCMining()
{
+ if (!pwalletMain)
+ return;
+
// getwork/getblocktemplate mining rewards paid here:
pMiningKey = new CReserveKey(pwalletMain);
}
void ShutdownRPCMining()
{
+ if (!pMiningKey)
+ return;
+
delete pMiningKey; pMiningKey = NULL;
}
+// Return average network hashes per second based on the last 'lookup' blocks,
+// or from the last difficulty change if 'lookup' is nonpositive.
+// If 'height' is nonnegative, compute the estimate at the time when a given block was found.
+Value GetNetworkHashPS(int lookup, int height) {
+ CBlockIndex *pb = chainActive[height];
+
+ if (pb == NULL || !pb->nHeight)
+ return 0;
+
+ // If lookup is -1, then use blocks since last difficulty change.
+ if (lookup <= 0)
+ lookup = pb->nHeight % 2016 + 1;
+
+ // If lookup is larger than chain, then set it to chain length.
+ if (lookup > pb->nHeight)
+ lookup = pb->nHeight;
+
+ CBlockIndex *pb0 = pb;
+ int64 minTime = pb0->GetBlockTime();
+ int64 maxTime = minTime;
+ for (int i = 0; i < lookup; i++) {
+ pb0 = pb0->pprev;
+ int64 time = pb0->GetBlockTime();
+ minTime = std::min(time, minTime);
+ maxTime = std::max(time, maxTime);
+ }
+
+ // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
+ if (minTime == maxTime)
+ return 0;
+
+ uint256 workDiff = pb->nChainWork - pb0->nChainWork;
+ int64 timeDiff = maxTime - minTime;
+
+ return (boost::int64_t)(workDiff.getdouble() / timeDiff);
+}
+
+Value getnetworkhashps(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2)
+ throw runtime_error(
+ "getnetworkhashps [blocks] [height]\n"
+ "Returns the estimated network hashes per second based on the last 120 blocks.\n"
+ "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
+ "Pass in [height] to estimate the network speed at the time when a certain block was found.");
+
+ return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
+}
+
+
Value getgenerate(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -34,6 +90,9 @@ Value getgenerate(const Array& params, bool fHelp)
"getgenerate\n"
"Returns true or false.");
+ if (!pMiningKey)
+ return false;
+
return GetBoolArg("-gen", false);
}
@@ -59,6 +118,7 @@ Value setgenerate(const Array& params, bool fHelp)
}
mapArgs["-gen"] = (fGenerate ? "1" : "0");
+ assert(pwalletMain != NULL);
GenerateBitcoins(fGenerate, pwalletMain);
return Value::null;
}
@@ -85,14 +145,15 @@ Value getmininginfo(const Array& params, bool fHelp)
"Returns an object containing mining-related information.");
Object obj;
- obj.push_back(Pair("blocks", (int)nBestHeight));
+ obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
- obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
+ obj.push_back(Pair("generate", getgenerate(params, false)));
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
+ obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("testnet", TestNet()));
return obj;
@@ -128,10 +189,10 @@ Value getwork(const Array& params, bool fHelp)
static CBlockIndex* pindexPrev;
static int64 nStart;
static CBlockTemplate* pblocktemplate;
- if (pindexPrev != pindexBest ||
+ if (pindexPrev != chainActive.Tip() ||
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
{
- if (pindexPrev != pindexBest)
+ if (pindexPrev != chainActive.Tip())
{
// Deallocate old blocks since they're obsolete now
mapNewBlock.clear();
@@ -145,7 +206,7 @@ Value getwork(const Array& params, bool fHelp)
// Store the pindexBest used before CreateNewBlock, to avoid races
nTransactionsUpdatedLast = nTransactionsUpdated;
- CBlockIndex* pindexPrevNew = pindexBest;
+ CBlockIndex* pindexPrevNew = chainActive.Tip();
nStart = GetTime();
// Create new block
@@ -207,6 +268,7 @@ Value getwork(const Array& params, bool fHelp)
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
+ assert(pwalletMain != NULL);
return CheckWork(pblock, *pwalletMain, *pMiningKey);
}
}
@@ -263,7 +325,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
static CBlockIndex* pindexPrev;
static int64 nStart;
static CBlockTemplate* pblocktemplate;
- if (pindexPrev != pindexBest ||
+ if (pindexPrev != chainActive.Tip() ||
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
{
// Clear pindexPrev so future calls make a new block, despite any failures from here on
@@ -271,7 +333,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
// Store the pindexBest used before CreateNewBlock, to avoid races
nTransactionsUpdatedLast = nTransactionsUpdated;
- CBlockIndex* pindexPrevNew = pindexBest;
+ CBlockIndex* pindexPrevNew = chainActive.Tip();
nStart = GetTime();
// Create new block
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index bd7bc0ba10..f78f034e32 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -19,6 +19,24 @@ Value getconnectioncount(const Array& params, bool fHelp)
return (int)vNodes.size();
}
+Value ping(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "ping\n"
+ "Requests that a ping be sent to all other nodes, to measure ping time.\n"
+ "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
+ "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.");
+
+ // Request that each node send a ping during next message processing pass
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pNode, vNodes) {
+ pNode->fPingQueued = true;
+ }
+
+ return Value::null;
+}
+
static void CopyNodeStats(std::vector<CNodeStats>& vstats)
{
vstats.clear();
@@ -54,6 +72,9 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes));
obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes));
obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
+ obj.push_back(Pair("pingtime", stats.dPingTime));
+ if (stats.dPingWait > 0.0)
+ obj.push_back(Pair("pingwait", stats.dPingWait));
obj.push_back(Pair("version", stats.nVersion));
obj.push_back(Pair("subver", stats.strSubVer));
obj.push_back(Pair("inbound", stats.fInbound));
@@ -202,3 +223,17 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
return ret;
}
+Value getnettotals(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 0)
+ throw runtime_error(
+ "getnettotals\n"
+ "Returns information about network traffic, including bytes in, bytes out,\n"
+ "and current time.");
+
+ Object obj;
+ obj.push_back(Pair("totalbytesrecv", static_cast< boost::uint64_t>(CNode::GetTotalBytesRecv())));
+ obj.push_back(Pair("totalbytessent", static_cast<boost::uint64_t>(CNode::GetTotalBytesSent())));
+ obj.push_back(Pair("timemillis", static_cast<boost::int64_t>(GetTimeMillis())));
+ return obj;
+}
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 580120f2a2..5384b65906 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -17,47 +17,15 @@ using namespace boost;
using namespace boost::assign;
using namespace json_spirit;
-//
-// Utilities: convert hex-encoded Values
-// (throws error if not hex).
-//
-uint256 ParseHashV(const Value& v, string strName)
-{
- string strHex;
- if (v.type() == str_type)
- strHex = v.get_str();
- if (!IsHex(strHex)) // Note: IsHex("") is false
- throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
- uint256 result;
- result.SetHex(strHex);
- return result;
-}
-uint256 ParseHashO(const Object& o, string strKey)
-{
- return ParseHashV(find_value(o, strKey), strKey);
-}
-vector<unsigned char> ParseHexV(const Value& v, string strName)
-{
- string strHex;
- if (v.type() == str_type)
- strHex = v.get_str();
- if (!IsHex(strHex))
- throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
- return ParseHex(strHex);
-}
-vector<unsigned char> ParseHexO(const Object& o, string strKey)
-{
- return ParseHexV(find_value(o, strKey), strKey);
-}
-
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
+void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
{
txnouttype type;
vector<CTxDestination> addresses;
int nRequired;
out.push_back(Pair("asm", scriptPubKey.ToString()));
- out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
+ if (fIncludeHex)
+ out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
{
@@ -106,7 +74,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
out.push_back(Pair("n", (boost::int64_t)i));
Object o;
- ScriptPubKeyToJSON(txout.scriptPubKey, o);
+ ScriptPubKeyToJSON(txout.scriptPubKey, o, false);
out.push_back(Pair("scriptPubKey", o));
vout.push_back(out);
}
@@ -119,9 +87,9 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
if (mi != mapBlockIndex.end() && (*mi).second)
{
CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
+ if (chainActive.Contains(pindex))
{
- entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
+ entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime));
}
@@ -203,6 +171,7 @@ Value listunspent(const Array& params, bool fHelp)
Array results;
vector<COutput> vecOutputs;
+ assert(pwalletMain != NULL);
pwalletMain->AvailableCoins(vecOutputs, false);
BOOST_FOREACH(const COutput& out, vecOutputs)
{
@@ -334,6 +303,29 @@ Value decoderawtransaction(const Array& params, bool fHelp)
return result;
}
+Value decodescript(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "decodescript <hex string>\n"
+ "Decode a hex-encoded script.");
+
+ RPCTypeCheck(params, list_of(str_type));
+
+ Object r;
+ CScript script;
+ if (params[0].get_str().size() > 0){
+ vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
+ script = CScript(scriptData.begin(), scriptData.end());
+ } else {
+ // Empty scripts are valid
+ }
+ ScriptPubKeyToJSON(script, r, false);
+
+ r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
+ return r;
+}
+
Value signrawtransaction(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 4)
@@ -467,7 +459,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
}
- const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
+ const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
int nHashType = SIGHASH_ALL;
if (params.size() > 3 && params[3].type() != null_type)
@@ -527,9 +519,9 @@ Value signrawtransaction(const Array& params, bool fHelp)
Value sendrawtransaction(const Array& params, bool fHelp)
{
- if (fHelp || params.size() < 1 || params.size() > 1)
+ if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "sendrawtransaction <hex string>\n"
+ "sendrawtransaction <hex string> [allowhighfees=false]\n"
"Submits raw transaction (serialized, hex-encoded) to local node and network.");
// parse hex string from parameter
@@ -537,6 +529,10 @@ Value sendrawtransaction(const Array& params, bool fHelp)
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
+ bool fOverrideFees = false;
+ if (params.size() > 1)
+ fOverrideFees = params[1].get_bool();
+
// deserialize binary data stream
try {
ssData >> tx;
@@ -554,7 +550,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
if (!fHave) {
// push to local node
CValidationState state;
- if (!mempool.accept(state, tx, false, NULL))
+ if (!mempool.accept(state, tx, false, NULL, !fOverrideFees))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); // TODO: report validation state
}
}
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 34bd4ffccf..f7341f7b69 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -21,7 +21,7 @@ static CCriticalSection cs_nWalletUnlockTime;
std::string HelpRequiringPassphrase()
{
- return pwalletMain->IsCrypted()
+ return pwalletMain && pwalletMain->IsCrypted()
? "\nrequires wallet passphrase to be set with walletpassphrase first"
: "";
}
@@ -72,18 +72,22 @@ Value getinfo(const Array& params, bool fHelp)
Object obj;
obj.push_back(Pair("version", (int)CLIENT_VERSION));
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
- obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
- obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
- obj.push_back(Pair("blocks", (int)nBestHeight));
+ if (pwalletMain) {
+ obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
+ obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
+ }
+ obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", TestNet()));
- obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
- obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
+ if (pwalletMain) {
+ obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
+ obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
+ }
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
- if (pwalletMain->IsCrypted())
+ if (pwalletMain && pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj;
@@ -176,6 +180,29 @@ Value getaccountaddress(const Array& params, bool fHelp)
}
+Value getrawchangeaddress(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 1)
+ throw runtime_error(
+ "getrawchangeaddress\n"
+ "Returns a new Bitcoin address, for receiving change. "
+ "This is for use with raw transactions, NOT normal use.");
+
+ if (!pwalletMain->IsLocked())
+ pwalletMain->TopUpKeyPool();
+
+ CReserveKey reservekey(pwalletMain);
+ CPubKey vchPubKey;
+ if (!reservekey.GetReservedKey(vchPubKey))
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error: Unable to obtain key for change");
+
+ reservekey.KeepKey();
+
+ CKeyID keyID = vchPubKey.GetID();
+
+ return CBitcoinAddress(keyID).ToString();
+}
+
Value setaccount(const Array& params, bool fHelp)
{
@@ -715,7 +742,7 @@ static CScript _createmultisig(const Array& params)
// Case 1: Bitcoin address and we have full public key:
CBitcoinAddress address(ks);
- if (address.IsValid())
+ if (pwalletMain && address.IsValid())
{
CKeyID keyID;
if (!address.GetKeyID(keyID))
@@ -1142,7 +1169,9 @@ Value listsinceblock(const Array& params, bool fHelp)
uint256 blockId = 0;
blockId.SetHex(params[0].get_str());
- pindex = CBlockLocator(blockId).GetBlockIndex();
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(blockId);
+ if (it != mapBlockIndex.end())
+ pindex = it->second;
}
if (params.size() > 1)
@@ -1153,7 +1182,7 @@ Value listsinceblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
}
- int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
+ int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
Array transactions;
@@ -1165,23 +1194,8 @@ Value listsinceblock(const Array& params, bool fHelp)
ListTransactions(tx, "*", 0, true, transactions);
}
- uint256 lastblock;
-
- if (target_confirms == 1)
- {
- lastblock = hashBestChain;
- }
- else
- {
- int target_height = pindexBest->nHeight + 1 - target_confirms;
-
- CBlockIndex *block;
- for (block = pindexBest;
- block && block->nHeight > target_height;
- block = block->pprev) { }
-
- lastblock = block ? block->GetBlockHash() : 0;
- }
+ CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
+ uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
Object ret;
ret.push_back(Pair("transactions", transactions));
@@ -1424,6 +1438,7 @@ public:
int nRequired;
ExtractDestinations(subscript, whichType, addresses, nRequired);
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
+ obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
Array a;
BOOST_FOREACH(const CTxDestination& addr, addresses)
a.push_back(CBitcoinAddress(addr).ToString());
@@ -1451,13 +1466,13 @@ Value validateaddress(const Array& params, bool fHelp)
CTxDestination dest = address.Get();
string currentAddress = address.ToString();
ret.push_back(Pair("address", currentAddress));
- bool fMine = IsMine(*pwalletMain, dest);
+ bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false;
ret.push_back(Pair("ismine", fMine));
if (fMine) {
Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
ret.insert(ret.end(), detail.begin(), detail.end());
}
- if (pwalletMain->mapAddressBook.count(dest))
+ if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
}
return ret;
diff --git a/src/script.cpp b/src/script.cpp
index 3c3e9cf3bf..ad2d35d94c 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -971,62 +971,118 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
+namespace {
+/** Wrapper that serializes like CTransaction, but with the modifications
+ * required for the signature hash done in-place
+ */
+class CTransactionSignatureSerializer {
+private:
+ const CTransaction &txTo; // reference to the spending transaction (the one being serialized)
+ const CScript &scriptCode; // output script being consumed
+ const unsigned int nIn; // input index of txTo being signed
+ const bool fAnyoneCanPay; // whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; // whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; // whether the hashtype is SIGHASH_NONE
-
-uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
-{
- if (nIn >= txTo.vin.size())
- {
- printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
- return 1;
+public:
+ CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
+ txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
+ fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
+ fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
+ fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}
+
+ /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
+ template<typename S>
+ void SerializeScriptCode(S &s, int nType, int nVersion) const {
+ CScript::const_iterator it = scriptCode.begin();
+ CScript::const_iterator itBegin = it;
+ opcodetype opcode;
+ unsigned int nCodeSeparators = 0;
+ while (scriptCode.GetOp(it, opcode)) {
+ if (opcode == OP_CODESEPARATOR)
+ nCodeSeparators++;
+ }
+ ::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
+ it = itBegin;
+ while (scriptCode.GetOp(it, opcode)) {
+ if (opcode == OP_CODESEPARATOR) {
+ s.write((char*)&itBegin[0], it-itBegin-1);
+ itBegin = it;
+ }
+ }
+ s.write((char*)&itBegin[0], it-itBegin);
}
- CTransaction txTmp(txTo);
- // In case concatenating two scripts ends up with two codeseparators,
- // or an extra one at the end, this prevents all those possible incompatibilities.
- scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
+ /** Serialize an input of txTo */
+ template<typename S>
+ void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) const {
+ // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
+ if (fAnyoneCanPay)
+ nInput = nIn;
+ // Serialize the prevout
+ ::Serialize(s, txTo.vin[nInput].prevout, nType, nVersion);
+ // Serialize the script
+ if (nInput != nIn)
+ // Blank out other inputs' signatures
+ ::Serialize(s, CScript(), nType, nVersion);
+ else
+ SerializeScriptCode(s, nType, nVersion);
+ // Serialize the nSequence
+ if (nInput != nIn && (fHashSingle || fHashNone))
+ // let the others update at will
+ ::Serialize(s, (int)0, nType, nVersion);
+ else
+ ::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion);
+ }
- // Blank out other inputs' signatures
- for (unsigned int i = 0; i < txTmp.vin.size(); i++)
- txTmp.vin[i].scriptSig = CScript();
- txTmp.vin[nIn].scriptSig = scriptCode;
+ /** Serialize an output of txTo */
+ template<typename S>
+ void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const {
+ if (fHashSingle && nOutput != nIn)
+ // Do not lock-in the txout payee at other indices as txin
+ ::Serialize(s, CTxOut(), nType, nVersion);
+ else
+ ::Serialize(s, txTo.vout[nOutput], nType, nVersion);
+ }
- // Blank out some of the outputs
- if ((nHashType & 0x1f) == SIGHASH_NONE)
- {
- // Wildcard payee
- txTmp.vout.clear();
+ /** Serialize txTo */
+ template<typename S>
+ void Serialize(S &s, int nType, int nVersion) const {
+ // Serialize nVersion
+ ::Serialize(s, txTo.nVersion, nType, nVersion);
+ // Serialize vin
+ unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
+ ::WriteCompactSize(s, nInputs);
+ for (unsigned int nInput = 0; nInput < nInputs; nInput++)
+ SerializeInput(s, nInput, nType, nVersion);
+ // Serialize vout
+ unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
+ ::WriteCompactSize(s, nOutputs);
+ for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
+ SerializeOutput(s, nOutput, nType, nVersion);
+ // Serialie nLockTime
+ ::Serialize(s, txTo.nLockTime, nType, nVersion);
+ }
+};
+}
- // Let the others update at will
- for (unsigned int i = 0; i < txTmp.vin.size(); i++)
- if (i != nIn)
- txTmp.vin[i].nSequence = 0;
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ if (nIn >= txTo.vin.size()) {
+ LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ return 1;
}
- else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
- {
- // Only lock-in the txout payee at same index as txin
- unsigned int nOut = nIn;
- if (nOut >= txTmp.vout.size())
- {
- printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
+
+ // Check for invalid use of SIGHASH_SINGLE
+ if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
+ if (nIn >= txTo.vout.size()) {
+ LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nIn);
return 1;
}
- txTmp.vout.resize(nOut+1);
- for (unsigned int i = 0; i < nOut; i++)
- txTmp.vout[i].SetNull();
-
- // Let the others update at will
- for (unsigned int i = 0; i < txTmp.vin.size(); i++)
- if (i != nIn)
- txTmp.vin[i].nSequence = 0;
}
- // Blank out other inputs completely, not recommended for open transactions
- if (nHashType & SIGHASH_ANYONECANPAY)
- {
- txTmp.vin[0] = txTmp.vin[nIn];
- txTmp.vin.resize(1);
- }
+ // Wrapper to serialize only the necessary parts of the transaction being signed
+ CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
diff --git a/src/script.h b/src/script.h
index 0ab47678e8..842b8512eb 100644
--- a/src/script.h
+++ b/src/script.h
@@ -553,6 +553,13 @@ public:
return true;
}
+ // Returns whether the script is guaranteed to fail at execution,
+ // regardless of the initial stack. This allows outputs to be pruned
+ // instantly when entering the UTXO set.
+ bool IsUnspendable() const
+ {
+ return (size() > 0 && *begin() == OP_RETURN);
+ }
void SetDestination(const CTxDestination& address);
void SetMultisig(int nRequired, const std::vector<CPubKey>& keys);
@@ -560,7 +567,7 @@ public:
void PrintHex() const
{
- printf("CScript(%s)\n", HexStr(begin(), end(), true).c_str());
+ LogPrintf("CScript(%s)\n", HexStr(begin(), end(), true).c_str());
}
std::string ToString() const
@@ -588,7 +595,7 @@ public:
void print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
CScriptID GetID() const
diff --git a/src/sync.cpp b/src/sync.cpp
index 1ac4403beb..29a455f9b2 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -10,8 +10,8 @@
#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
{
- printf("LOCKCONTENTION: %s\n", pszName);
- printf("Locker: %s:%d\n", pszFile, nLine);
+ LogPrintf("LOCKCONTENTION: %s\n", pszName);
+ LogPrintf("Locker: %s:%d\n", pszFile, nLine);
}
#endif /* DEBUG_LOCKCONTENTION */
@@ -56,20 +56,20 @@ static boost::thread_specific_ptr<LockStack> lockstack;
static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
- printf("POTENTIAL DEADLOCK DETECTED\n");
- printf("Previous lock order was:\n");
+ LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
+ LogPrintf("Previous lock order was:\n");
BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
{
- if (i.first == mismatch.first) printf(" (1)");
- if (i.first == mismatch.second) printf(" (2)");
- printf(" %s\n", i.second.ToString().c_str());
+ if (i.first == mismatch.first) LogPrintf(" (1)");
+ if (i.first == mismatch.second) LogPrintf(" (2)");
+ LogPrintf(" %s\n", i.second.ToString().c_str());
}
- printf("Current lock order is:\n");
+ LogPrintf("Current lock order is:\n");
BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
{
- if (i.first == mismatch.first) printf(" (1)");
- if (i.first == mismatch.second) printf(" (2)");
- printf(" %s\n", i.second.ToString().c_str());
+ if (i.first == mismatch.first) LogPrintf(" (1)");
+ if (i.first == mismatch.second) LogPrintf(" (2)");
+ LogPrintf(" %s\n", i.second.ToString().c_str());
}
}
@@ -78,7 +78,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
if (lockstack.get() == NULL)
lockstack.reset(new LockStack);
- if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
+ if (fDebug) LogPrintf("Locking: %s\n", locklocation.ToString().c_str());
dd_mutex.lock();
(*lockstack).push_back(std::make_pair(c, locklocation));
@@ -108,7 +108,7 @@ static void pop_lock()
if (fDebug)
{
const CLockLocation& locklocation = (*lockstack).rbegin()->second;
- printf("Unlocked: %s\n", locklocation.ToString().c_str());
+ LogPrintf("Unlocked: %s\n", locklocation.ToString().c_str());
}
dd_mutex.lock();
(*lockstack).pop_back();
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
new file mode 100644
index 0000000000..c3495095d9
--- /dev/null
+++ b/src/test/Makefile.am
@@ -0,0 +1,41 @@
+include $(top_srcdir)/src/Makefile.include
+
+AM_CPPFLAGS = $(INCLUDES) -I$(top_builddir)/src/obj \
+ -I$(top_srcdir)/src/leveldb/include -I$(top_srcdir)/src/leveldb/helpers \
+ -I$(top_srcdir)/src $(BOOST_INCLUDES) $(BDB_CPPFLAGS)
+
+AM_LDFLAGS = $(PTHREAD_CFLAGS)
+
+bin_PROGRAMS = test_bitcoin
+
+TESTS = test_bitcoin
+
+JSON_TEST_FILES= data/script_valid.json \
+ data/base58_keys_valid.json data/sig_canonical.json \
+ data/sig_noncanonical.json \
+ data/base58_encode_decode.json \
+ data/base58_keys_invalid.json \
+ data/script_invalid.json data/tx_invalid.json \
+ data/tx_valid.json
+
+RAW_TEST_FILES = data/alertTests.raw
+
+BUILT_SOURCES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
+
+# test_bitcoin binary #
+test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS)
+test_bitcoin_LDADD = $(LIBBITCOIN) $(LIBLEVELDB) $(LIBMEMENV) \
+ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(BDB_LIBS)
+test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \
+ allocator_tests.cpp base32_tests.cpp base58_tests.cpp base64_tests.cpp \
+ bignum_tests.cpp bloom_tests.cpp canonical_tests.cpp checkblock_tests.cpp \
+ Checkpoints_tests.cpp compress_tests.cpp DoS_tests.cpp getarg_tests.cpp \
+ key_tests.cpp miner_tests.cpp mruset_tests.cpp multisig_tests.cpp \
+ netbase_tests.cpp pmt_tests.cpp rpc_tests.cpp script_P2SH_tests.cpp \
+ script_tests.cpp serialize_tests.cpp sigopcount_tests.cpp test_bitcoin.cpp \
+ transaction_tests.cpp uint160_tests.cpp uint256_tests.cpp util_tests.cpp \
+ wallet_tests.cpp sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
+
+nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES)
+
+CLEANFILES = *.gcda *.gcno $(BUILT_SOURCES)
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index f7a11376d3..cb941943f7 100644
--- a/src/test/alert_tests.cpp
+++ b/src/test/alert_tests.cpp
@@ -9,6 +9,7 @@
#include "alert.h"
#include "serialize.h"
#include "util.h"
+#include "data/alertTests.raw.h"
#if 0
//
@@ -71,27 +72,13 @@ struct ReadAlerts
{
ReadAlerts()
{
- std::string filename("alertTests");
- namespace fs = boost::filesystem;
- fs::path testFile = fs::current_path() / "test" / "data" / filename;
-#ifdef TEST_DATA_DIR
- if (!fs::exists(testFile))
- {
- testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename;
- }
-#endif
- FILE* fp = fopen(testFile.string().c_str(), "rb");
- if (!fp) return;
-
-
- CAutoFile filein = CAutoFile(fp, SER_DISK, CLIENT_VERSION);
- if (!filein) return;
-
+ std::vector<unsigned char> vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests));
+ CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
try {
- while (!feof(filein))
+ while (stream.good())
{
CAlert alert;
- filein >> alert;
+ stream >> alert;
alerts.push_back(alert);
}
}
@@ -125,6 +112,9 @@ BOOST_AUTO_TEST_CASE(AlertApplies)
{
BOOST_CHECK(alert.CheckSignature());
}
+
+ BOOST_CHECK(alerts.size() >= 3);
+
// Matches:
BOOST_CHECK(alerts[0].AppliesTo(1, ""));
BOOST_CHECK(alerts[0].AppliesTo(70001, ""));
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index af65416485..05675685bd 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -2,20 +2,21 @@
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
+#include "data/base58_encode_decode.json.h"
+#include "data/base58_keys_invalid.json.h"
+#include "data/base58_keys_valid.json.h"
#include "base58.h"
#include "util.h"
-
using namespace json_spirit;
-extern Array read_json(const std::string& filename);
+extern Array read_json(const std::string& jsondata);
BOOST_AUTO_TEST_SUITE(base58_tests)
// Goal: test low-level base58 encoding functionality
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
- Array tests = read_json("base58_encode_decode.json");
-
+ Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -36,7 +37,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
// Goal: test low-level base58 decoding functionality
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
- Array tests = read_json("base58_encode_decode.json");
+ Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
std::vector<unsigned char> result;
BOOST_FOREACH(Value& tv, tests)
@@ -104,7 +105,7 @@ public:
// Goal: check that parsed keys match test payload
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
- Array tests = read_json("base58_keys_valid.json");
+ Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
@@ -163,7 +164,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
// Goal: check that generated keys match test vectors
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
- Array tests = read_json("base58_keys_valid.json");
+ Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
std::vector<unsigned char> result;
BOOST_FOREACH(Value& tv, tests)
{
@@ -231,7 +232,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
// Goal: check that base58 parsing code is robust against a variety of corrupted data
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
- Array tests = read_json("base58_keys_invalid.json"); // Negative testcases
+ Array tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
diff --git a/src/test/canonical_tests.cpp b/src/test/canonical_tests.cpp
index 09988da259..ec32ceb8a4 100644
--- a/src/test/canonical_tests.cpp
+++ b/src/test/canonical_tests.cpp
@@ -8,13 +8,15 @@
#include "key.h"
#include "script.h"
#include "util.h"
+#include "data/sig_noncanonical.json.h"
+#include "data/sig_canonical.json.h"
using namespace std;
using namespace json_spirit;
// In script_tests.cpp
-extern Array read_json(const std::string& filename);
+extern Array read_json(const std::string& jsondata);
BOOST_AUTO_TEST_SUITE(canonical_tests)
@@ -58,7 +60,7 @@ bool static IsCanonicalSignature_OpenSSL(const std::vector<unsigned char> &vchSi
BOOST_AUTO_TEST_CASE(script_canon)
{
- Array tests = read_json("sig_canonical.json");
+ Array tests = read_json(std::string(json_tests::sig_canonical, json_tests::sig_canonical + sizeof(json_tests::sig_canonical)));
BOOST_FOREACH(Value &tv, tests) {
string test = tv.get_str();
@@ -72,7 +74,7 @@ BOOST_AUTO_TEST_CASE(script_canon)
BOOST_AUTO_TEST_CASE(script_noncanon)
{
- Array tests = read_json("sig_noncanonical.json");
+ Array tests = read_json(std::string(json_tests::sig_noncanonical, json_tests::sig_noncanonical + sizeof(json_tests::sig_noncanonical)));
BOOST_FOREACH(Value &tv, tests) {
string test = tv.get_str();
diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
index 5675c40e76..e34680db99 100644
--- a/src/test/checkblock_tests.cpp
+++ b/src/test/checkblock_tests.cpp
@@ -19,7 +19,7 @@ bool
read_block(const std::string& filename, CBlock& block)
{
namespace fs = boost::filesystem;
- fs::path testFile = fs::current_path() / "test" / "data" / filename;
+ fs::path testFile = fs::current_path() / "data" / filename;
#ifdef TEST_DATA_DIR
if (!fs::exists(testFile))
{
diff --git a/src/test/data/alertTests b/src/test/data/alertTests.raw
index 7fc4528961..7fc4528961 100644
--- a/src/test/data/alertTests
+++ b/src/test/data/alertTests.raw
Binary files differ
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 8183504147..67165760b2 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -65,10 +65,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
pblock->nVersion = 1;
- pblock->nTime = pindexBest->GetMedianTimePast()+1;
+ pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
pblock->vtx[0].vin[0].scriptSig = CScript();
pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce);
- pblock->vtx[0].vin[0].scriptSig.push_back(pindexBest->nHeight);
+ pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height());
pblock->vtx[0].vout[0].scriptPubKey = CScript();
if (txFirst.size() < 2)
txFirst.push_back(new CTransaction(pblock->vtx[0]));
@@ -83,6 +83,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// Just to make sure we can still make simple blocks
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ delete pblocktemplate;
// block sigops > limit: 1000 CHECKMULTISIG + 1
tx.vin.resize(1);
@@ -192,14 +193,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.clear();
// subsidy changing
- int nHeight = pindexBest->nHeight;
- pindexBest->nHeight = 209999;
+ int nHeight = chainActive.Height();
+ chainActive.Tip()->nHeight = 209999;
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
delete pblocktemplate;
- pindexBest->nHeight = 210000;
+ chainActive.Tip()->nHeight = 210000;
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
delete pblocktemplate;
- pindexBest->nHeight = nHeight;
+ chainActive.Tip()->nHeight = nHeight;
+
+ BOOST_FOREACH(CTransaction *tx, txFirst)
+ delete tx;
}
BOOST_AUTO_TEST_CASE(sha256transform_equality)
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 9ef932b5b4..7f6f141c62 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -19,7 +19,7 @@ using namespace boost::assign;
typedef vector<unsigned char> valtype;
-extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
BOOST_AUTO_TEST_SUITE(multisig_tests)
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index c1f6f178db..32be914414 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -14,12 +14,14 @@
#include "main.h"
#include "wallet.h"
+#include "data/script_invalid.json.h"
+#include "data/script_valid.json.h"
using namespace std;
using namespace json_spirit;
using namespace boost::algorithm;
-extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
@@ -90,34 +92,15 @@ ParseScript(string s)
}
Array
-read_json(const std::string& filename)
+read_json(const std::string& jsondata)
{
- namespace fs = boost::filesystem;
- fs::path testFile = fs::current_path() / "test" / "data" / filename;
-
-#ifdef TEST_DATA_DIR
- if (!fs::exists(testFile))
- {
- testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename;
- }
-#endif
-
- ifstream ifs(testFile.string().c_str(), ifstream::in);
Value v;
- if (!read_stream(ifs, v))
- {
- if (ifs.fail())
- BOOST_ERROR("Cound not find/open " << filename);
- else
- BOOST_ERROR("JSON syntax error in " << filename);
- return Array();
- }
- if (v.type() != array_type)
+
+ if (!read_string(jsondata, v) || v.type() != array_type)
{
- BOOST_ERROR(filename << " does not contain a json array");
+ BOOST_ERROR("Parse error.");
return Array();
}
-
return v.get_array();
}
@@ -130,7 +113,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
// Inner arrays are [ "scriptSig", "scriptPubKey" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
- Array tests = read_json("script_valid.json");
+ Array tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
BOOST_FOREACH(Value& tv, tests)
{
@@ -154,7 +137,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
BOOST_AUTO_TEST_CASE(script_invalid)
{
// Scripts that should evaluate as invalid
- Array tests = read_json("script_invalid.json");
+ Array tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
BOOST_FOREACH(Value& tv, tests)
{
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
new file mode 100644
index 0000000000..f098d46186
--- /dev/null
+++ b/src/test/sighash_tests.cpp
@@ -0,0 +1,120 @@
+#include <boost/test/unit_test.hpp>
+
+#include "main.h"
+#include "util.h"
+
+extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+
+// Old script.cpp SignatureHash function
+uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ if (nIn >= txTo.vin.size())
+ {
+ printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ return 1;
+ }
+ CTransaction txTmp(txTo);
+
+ // In case concatenating two scripts ends up with two codeseparators,
+ // or an extra one at the end, this prevents all those possible incompatibilities.
+ scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
+
+ // Blank out other inputs' signatures
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ txTmp.vin[i].scriptSig = CScript();
+ txTmp.vin[nIn].scriptSig = scriptCode;
+
+ // Blank out some of the outputs
+ if ((nHashType & 0x1f) == SIGHASH_NONE)
+ {
+ // Wildcard payee
+ txTmp.vout.clear();
+
+ // Let the others update at will
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ if (i != nIn)
+ txTmp.vin[i].nSequence = 0;
+ }
+ else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
+ {
+ // Only lock-in the txout payee at same index as txin
+ unsigned int nOut = nIn;
+ if (nOut >= txTmp.vout.size())
+ {
+ printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
+ return 1;
+ }
+ txTmp.vout.resize(nOut+1);
+ for (unsigned int i = 0; i < nOut; i++)
+ txTmp.vout[i].SetNull();
+
+ // Let the others update at will
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ if (i != nIn)
+ txTmp.vin[i].nSequence = 0;
+ }
+
+ // Blank out other inputs completely, not recommended for open transactions
+ if (nHashType & SIGHASH_ANYONECANPAY)
+ {
+ txTmp.vin[0] = txTmp.vin[nIn];
+ txTmp.vin.resize(1);
+ }
+
+ // Serialize and hash
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << txTmp << nHashType;
+ return ss.GetHash();
+}
+
+void static RandomScript(CScript &script) {
+ static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR};
+ script = CScript();
+ int ops = (insecure_rand() % 10);
+ for (int i=0; i<ops; i++)
+ script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
+}
+
+void static RandomTransaction(CTransaction &tx, bool fSingle) {
+ tx.nVersion = insecure_rand();
+ tx.vin.clear();
+ tx.vout.clear();
+ tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
+ int ins = (insecure_rand() % 4) + 1;
+ int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
+ for (int in = 0; in < ins; in++) {
+ tx.vin.push_back(CTxIn());
+ CTxIn &txin = tx.vin.back();
+ txin.prevout.hash = GetRandHash();
+ txin.prevout.n = insecure_rand() % 4;
+ RandomScript(txin.scriptSig);
+ txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1;
+ }
+ for (int out = 0; out < outs; out++) {
+ tx.vout.push_back(CTxOut());
+ CTxOut &txout = tx.vout.back();
+ txout.nValue = insecure_rand() % 100000000;
+ RandomScript(txout.scriptPubKey);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE(sighash_tests)
+
+BOOST_AUTO_TEST_CASE(sighash_test)
+{
+ seed_insecure_rand(false);
+
+ for (int i=0; i<50000; i++) {
+ int nHashType = insecure_rand();
+ CTransaction txTo;
+ RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
+ CScript scriptCode;
+ RandomScript(scriptCode);
+ int nIn = insecure_rand() % txTo.vin.size();
+ BOOST_CHECK(SignatureHash(scriptCode, txTo, nIn, nHashType) ==
+ SignatureHashOld(scriptCode, txTo, nIn, nHashType));
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 0c7475b4f2..416b93ab33 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -5,12 +5,14 @@
#include "main.h"
#include "wallet.h"
+#include "data/tx_invalid.json.h"
+#include "data/tx_valid.json.h"
using namespace std;
using namespace json_spirit;
// In script_tests.cpp
-extern Array read_json(const std::string& filename);
+extern Array read_json(const std::string& jsondata);
extern CScript ParseScript(string s);
BOOST_AUTO_TEST_SUITE(transaction_tests)
@@ -22,7 +24,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// Inner arrays are either [ "comment" ]
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
// ... where all scripts are stringified scripts.
- Array tests = read_json("tx_valid.json");
+ Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
BOOST_FOREACH(Value& tv, tests)
{
@@ -91,7 +93,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// Inner arrays are either [ "comment" ]
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
// ... where all scripts are stringified scripts.
- Array tests = read_json("tx_invalid.json");
+ Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
BOOST_FOREACH(Value& tv, tests)
{
diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp
index a14f6b2b70..51f3b27c8b 100644
--- a/src/test/wallet_tests.cpp
+++ b/src/test/wallet_tests.cpp
@@ -289,6 +289,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
BOOST_CHECK_NE(fails, RANDOM_REPEATS);
}
}
+ empty_wallet();
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 34836eaa97..24ee8ec3e8 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -55,7 +55,7 @@ bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
}
bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
- printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
+ LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
CLevelDBBatch batch;
for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
@@ -223,10 +223,6 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
- // Watch for genesis block
- if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == Params().HashGenesisBlock())
- pindexGenesisBlock = pindexNew;
-
if (!pindexNew->CheckIndex())
return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
diff --git a/src/uint256.h b/src/uint256.h
index 2a252c94f3..45ab8abb5e 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -654,39 +654,39 @@ inline int Testuint256AdHoc(std::vector<std::string> vArg)
uint256 g(0);
- printf("%s\n", g.ToString().c_str());
- g--; printf("g--\n");
- printf("%s\n", g.ToString().c_str());
- g--; printf("g--\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
- g++; printf("g++\n");
- printf("%s\n", g.ToString().c_str());
+ LogPrintf("%s\n", g.ToString().c_str());
+ g--; LogPrintf("g--\n");
+ LogPrintf("%s\n", g.ToString().c_str());
+ g--; LogPrintf("g--\n");
+ LogPrintf("%s\n", g.ToString().c_str());
+ g++; LogPrintf("g++\n");
+ LogPrintf("%s\n", g.ToString().c_str());
+ g++; LogPrintf("g++\n");
+ LogPrintf("%s\n", g.ToString().c_str());
+ g++; LogPrintf("g++\n");
+ LogPrintf("%s\n", g.ToString().c_str());
+ g++; LogPrintf("g++\n");
+ LogPrintf("%s\n", g.ToString().c_str());
uint256 a(7);
- printf("a=7\n");
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("a=7\n");
+ LogPrintf("%s\n", a.ToString().c_str());
uint256 b;
- printf("b undefined\n");
- printf("%s\n", b.ToString().c_str());
+ LogPrintf("b undefined\n");
+ LogPrintf("%s\n", b.ToString().c_str());
int c = 3;
a = c;
a.pn[3] = 15;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
uint256 k(c);
a = 5;
a.pn[3] = 15;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
b = 1;
b <<= 52;
@@ -694,86 +694,86 @@ inline int Testuint256AdHoc(std::vector<std::string> vArg)
a ^= 0x500;
- printf("a %s\n", a.ToString().c_str());
+ LogPrintf("a %s\n", a.ToString().c_str());
a = a | b | (uint256)0x1000;
- printf("a %s\n", a.ToString().c_str());
- printf("b %s\n", b.ToString().c_str());
+ LogPrintf("a %s\n", a.ToString().c_str());
+ LogPrintf("b %s\n", b.ToString().c_str());
a = 0xfffffffe;
a.pn[4] = 9;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a++;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a++;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a++;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a++;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a--;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a--;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a--;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
uint256 d = a--;
- printf("%s\n", d.ToString().c_str());
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", d.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a--;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
a--;
- printf("%s\n", a.ToString().c_str());
+ LogPrintf("%s\n", a.ToString().c_str());
d = a;
- printf("%s\n", d.ToString().c_str());
- for (int i = uint256::WIDTH-1; i >= 0; i--) printf("%08x", d.pn[i]); printf("\n");
+ LogPrintf("%s\n", d.ToString().c_str());
+ for (int i = uint256::WIDTH-1; i >= 0; i--) LogPrintf("%08x", d.pn[i]); LogPrintf("\n");
uint256 neg = d;
neg = ~neg;
- printf("%s\n", neg.ToString().c_str());
+ LogPrintf("%s\n", neg.ToString().c_str());
uint256 e = uint256("0xABCDEF123abcdef12345678909832180000011111111");
- printf("\n");
- printf("%s\n", e.ToString().c_str());
+ LogPrintf("\n");
+ LogPrintf("%s\n", e.ToString().c_str());
- printf("\n");
+ LogPrintf("\n");
uint256 x1 = uint256("0xABCDEF123abcdef12345678909832180000011111111");
uint256 x2;
- printf("%s\n", x1.ToString().c_str());
+ LogPrintf("%s\n", x1.ToString().c_str());
for (int i = 0; i < 270; i += 4)
{
x2 = x1 << i;
- printf("%s\n", x2.ToString().c_str());
+ LogPrintf("%s\n", x2.ToString().c_str());
}
- printf("\n");
- printf("%s\n", x1.ToString().c_str());
+ LogPrintf("\n");
+ LogPrintf("%s\n", x1.ToString().c_str());
for (int i = 0; i < 270; i += 4)
{
x2 = x1;
x2 >>= i;
- printf("%s\n", x2.ToString().c_str());
+ LogPrintf("%s\n", x2.ToString().c_str());
}
for (int i = 0; i < 100; i++)
{
uint256 k = (~uint256(0) >> i);
- printf("%s\n", k.ToString().c_str());
+ LogPrintf("%s\n", k.ToString().c_str());
}
for (int i = 0; i < 100; i++)
{
uint256 k = (~uint256(0) << i);
- printf("%s\n", k.ToString().c_str());
+ LogPrintf("%s\n", k.ToString().c_str());
}
return (0);
diff --git a/src/util.cpp b/src/util.cpp
index 136a035485..cfaf5bdf8c 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -78,7 +78,6 @@ bool fPrintToConsole = false;
bool fPrintToDebugger = false;
bool fDaemon = false;
bool fServer = false;
-bool fCommandLine = false;
string strMiscWarning;
bool fNoListen = false;
bool fLogTimestamps = false;
@@ -166,7 +165,7 @@ void RandAddSeedPerfmon()
{
RAND_add(pdata, nSize, nSize/100.0);
OPENSSL_cleanse(pdata, nSize);
- printf("RandAddSeed() %lu bytes\n", nSize);
+ LogPrint("rand", "RandAddSeed() %lu bytes\n", nSize);
}
#endif
}
@@ -198,15 +197,7 @@ uint256 GetRandHash()
return hash;
}
-
-
-
-
-
-
-//
-// OutputDebugStringF (aka printf -- there is a #define that we really
-// should get rid of one day) has been broken a couple of times now
+// LogPrintf() has been broken a couple of times now
// by well-meaning people adding mutexes in the most straightforward way.
// It breaks because it may be called by global destructors during shutdown.
// Since the order of destruction of static/global objects is undefined,
@@ -233,8 +224,16 @@ static void DebugPrintInit()
mutexDebugLog = new boost::mutex();
}
-int OutputDebugStringF(const char* pszFormat, ...)
+int LogPrint(const char* category, const char* pszFormat, ...)
{
+ if (category != NULL)
+ {
+ if (!fDebug) return 0;
+ const vector<string>& categories = mapMultiArgs["-debug"];
+ if (find(categories.begin(), categories.end(), string(category)) == categories.end())
+ return 0;
+ }
+
int ret = 0; // Returns total number of characters written
if (fPrintToConsole)
{
@@ -360,7 +359,7 @@ bool error(const char *format, ...)
va_start(arg_ptr, format);
std::string str = vstrprintf(format, arg_ptr);
va_end(arg_ptr);
- printf("ERROR: %s\n", str.c_str());
+ LogPrintf("ERROR: %s\n", str.c_str());
return false;
}
@@ -994,13 +993,13 @@ static std::string FormatException(std::exception* pex, const char* pszThread)
void LogException(std::exception* pex, const char* pszThread)
{
std::string message = FormatException(pex, pszThread);
- printf("\n%s", message.c_str());
+ LogPrintf("\n%s", message.c_str());
}
void PrintException(std::exception* pex, const char* pszThread)
{
std::string message = FormatException(pex, pszThread);
- printf("\n\n************************\n%s\n", message.c_str());
+ LogPrintf("\n\n************************\n%s\n", message.c_str());
fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
strMiscWarning = message;
throw;
@@ -1009,7 +1008,7 @@ void PrintException(std::exception* pex, const char* pszThread)
void PrintExceptionContinue(std::exception* pex, const char* pszThread)
{
std::string message = FormatException(pex, pszThread);
- printf("\n\n************************\n%s\n", message.c_str());
+ LogPrintf("\n\n************************\n%s\n", message.c_str());
fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
strMiscWarning = message;
}
@@ -1057,7 +1056,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
fs::path &path = pathCached[nNet];
- // This can be called during exceptions by printf, so we cache the
+ // This can be called during exceptions by LogPrintf(), so we cache the
// value so we don't have to do memory allocations after that.
if (!path.empty())
return path;
@@ -1156,6 +1155,8 @@ void FileCommit(FILE *fileout)
#else
#if defined(__linux__) || defined(__NetBSD__)
fdatasync(fileno(fileout));
+ #elif defined(__APPLE__) && defined(F_FULLFSYNC)
+ fcntl(fileno(fileout), F_FULLFSYNC, 0);
#else
fsync(fileno(fileout));
#endif
@@ -1320,7 +1321,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
// Add data
vTimeOffsets.input(nOffsetSample);
- printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
+ LogPrintf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{
int64 nMedian = vTimeOffsets.median();
@@ -1348,17 +1349,17 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
fDone = true;
string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
- printf("*** %s\n", strMessage.c_str());
+ LogPrintf("*** %s\n", strMessage.c_str());
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
}
}
}
if (fDebug) {
BOOST_FOREACH(int64 n, vSorted)
- printf("%+"PRI64d" ", n);
- printf("| ");
+ LogPrintf("%+"PRI64d" ", n);
+ LogPrintf("| ");
}
- printf("nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
+ LogPrintf("nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
}
}
@@ -1420,7 +1421,7 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
return fs::path(pszPath);
}
- printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
+ LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
return fs::path("");
}
#endif
@@ -1440,7 +1441,7 @@ boost::filesystem::path GetTempPath() {
path = boost::filesystem::path("/tmp");
#endif
if (path.empty() || !boost::filesystem::is_directory(path)) {
- printf("GetTempPath(): failed to find temp path\n");
+ LogPrintf("GetTempPath(): failed to find temp path\n");
return boost::filesystem::path("");
}
return path;
@@ -1451,7 +1452,7 @@ void runCommand(std::string strCommand)
{
int nErr = ::system(strCommand.c_str());
if (nErr)
- printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr);
+ LogPrintf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr);
}
void RenameThread(const char* name)
diff --git a/src/util.h b/src/util.h
index f246412de0..c3fb01dbf0 100644
--- a/src/util.h
+++ b/src/util.h
@@ -91,7 +91,6 @@ T* alignup(T* p)
}
#ifdef WIN32
-#define MSG_NOSIGNAL 0
#define MSG_DONTWAIT 0
#ifndef S_IRUSR
@@ -111,11 +110,13 @@ inline void MilliSleep(int64 n)
// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
// until fixed in 1.52. Use the deprecated sleep method for the broken case.
// See: https://svn.boost.org/trac/boost/ticket/7238
-
-#if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
+#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
-#else
+#elif defined(HAVE_WORKING_BOOST_SLEEP)
boost::this_thread::sleep(boost::posix_time::milliseconds(n));
+#else
+ //should never get here
+#error missing boost sleep implementation
#endif
}
@@ -144,7 +145,6 @@ extern bool fPrintToConsole;
extern bool fPrintToDebugger;
extern bool fDaemon;
extern bool fServer;
-extern bool fCommandLine;
extern std::string strMiscWarning;
extern bool fNoListen;
extern bool fLogTimestamps;
@@ -152,7 +152,10 @@ extern volatile bool fReopenDebugLog;
void RandAddSeed();
void RandAddSeedPerfmon();
-int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...);
+
+// Print to debug.log if -debug=category switch is given OR category is NULL.
+int ATTR_WARN_PRINTF(2,3) LogPrint(const char* category, const char* pszFormat, ...);
+#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
/*
Rationale for the real_strprintf / strprintf construction:
@@ -172,14 +175,6 @@ std::string vstrprintf(const char *format, va_list ap);
bool ATTR_WARN_PRINTF(1,2) error(const char *format, ...);
-/* Redefine printf so that it directs output to debug.log
- *
- * Do this *after* defining the other printf-like functions, because otherwise the
- * __attribute__((format(printf,X,Y))) gets expanded to __attribute__((format(OutputDebugStringF,X,Y)))
- * which confuses gcc.
- */
-#define printf OutputDebugStringF
-
void LogException(std::exception* pex, const char* pszThread);
void PrintException(std::exception* pex, const char* pszThread);
void PrintExceptionContinue(std::exception* pex, const char* pszThread);
@@ -316,12 +311,12 @@ inline std::string HexStr(const T& vch, bool fSpaces=false)
template<typename T>
void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true)
{
- printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
+ LogPrintf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
}
inline void PrintHex(const std::vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true)
{
- printf(pszFormat, HexStr(vch, fSpaces).c_str());
+ LogPrintf(pszFormat, HexStr(vch, fSpaces).c_str());
}
inline int64 GetPerformanceCounter()
@@ -521,7 +516,7 @@ inline void SetThreadPriority(int nPriority)
// PRIO_MAX is not defined on Solaris
#ifndef PRIO_MAX
- #define PRIO_MAX 20
+#define PRIO_MAX 20
#endif
#define THREAD_PRIORITY_LOWEST PRIO_MAX
#define THREAD_PRIORITY_BELOW_NORMAL 2
@@ -559,7 +554,7 @@ template <typename Callable> void LoopForever(const char* name, Callable func,
{
std::string s = strprintf("bitcoin-%s", name);
RenameThread(s.c_str());
- printf("%s thread start\n", name);
+ LogPrintf("%s thread start\n", name);
try
{
while (1)
@@ -570,7 +565,7 @@ template <typename Callable> void LoopForever(const char* name, Callable func,
}
catch (boost::thread_interrupted)
{
- printf("%s thread stop\n", name);
+ LogPrintf("%s thread stop\n", name);
throw;
}
catch (std::exception& e) {
@@ -587,13 +582,13 @@ template <typename Callable> void TraceThread(const char* name, Callable func)
RenameThread(s.c_str());
try
{
- printf("%s thread start\n", name);
+ LogPrintf("%s thread start\n", name);
func();
- printf("%s thread exit\n", name);
+ LogPrintf("%s thread exit\n", name);
}
catch (boost::thread_interrupted)
{
- printf("%s thread interrupt\n", name);
+ LogPrintf("%s thread interrupt\n", name);
throw;
}
catch (std::exception& e) {
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 7a3855c025..0f0ce7e631 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -159,7 +159,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
- printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
+ LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
@@ -267,7 +267,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
- printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
+ LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
@@ -368,10 +368,10 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
{
CWalletTx& wtx = (*mi).second;
if (txin.prevout.n >= wtx.vout.size())
- printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
+ LogPrintf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
{
- printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ LogPrintf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkSpent(txin.prevout.n);
wtx.WriteToDisk();
NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
@@ -446,9 +446,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
}
else
- printf("AddToWallet() : found %s in block %s not in index\n",
- wtxIn.GetHash().ToString().c_str(),
- wtxIn.hashBlock.ToString().c_str());
+ LogPrintf("AddToWallet() : found %s in block %s not in index\n",
+ wtxIn.GetHash().ToString().c_str(),
+ wtxIn.hashBlock.ToString().c_str());
}
}
@@ -476,7 +476,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
}
//// debug print
- printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
// Write to disk
if (fInsertedNew || fUpdated)
@@ -677,8 +677,8 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
vector<unsigned char> vchPubKey;
if (!ExtractDestination(txout.scriptPubKey, address))
{
- printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
- this->GetHash().ToString().c_str());
+ LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
+ this->GetHash().ToString().c_str());
}
// Don't report 'change' txouts
@@ -799,7 +799,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
// no need to read and scan block, if block was created before
// our wallet birthday (as adjusted for block time variability)
if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
continue;
}
@@ -810,7 +810,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
ret++;
}
- pindex = pindex->GetNextInMainChain();
+ pindex = chainActive.Next(pindex);
}
}
return ret;
@@ -849,7 +849,7 @@ void CWallet::ReacceptWalletTransactions()
}
if (fUpdated)
{
- printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ LogPrintf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkDirty();
wtx.WriteToDisk();
}
@@ -864,7 +864,7 @@ void CWallet::ReacceptWalletTransactions()
if (fMissing)
{
// TODO: optimize this to scan just part of the block chain?
- if (ScanForWalletTransactions(pindexGenesisBlock))
+ if (ScanForWalletTransactions(chainActive.Genesis()))
fRepeat = true; // Found missing transactions: re-do re-accept.
}
}
@@ -882,7 +882,7 @@ void CWalletTx::RelayWalletTransaction()
{
if (GetDepthInMainChain() == 0) {
uint256 hash = GetHash();
- printf("Relaying wtx %s\n", hash.ToString().c_str());
+ LogPrintf("Relaying wtx %s\n", hash.ToString().c_str());
RelayTransaction((CTransaction)*this, hash);
}
}
@@ -905,7 +905,7 @@ void CWallet::ResendWalletTransactions()
nLastResend = GetTime();
// Rebroadcast any of our txes that aren't in a block yet
- printf("ResendWalletTransactions()\n");
+ LogPrintf("ResendWalletTransactions()\n");
{
LOCK(cs_wallet);
// Sort them in chronological order
@@ -1145,12 +1145,11 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
nValueRet += vValue[i].first;
}
- //// debug print
- printf("SelectCoins() best subset: ");
+ LogPrint("selectcoins", "SelectCoins() best subset: ");
for (unsigned int i = 0; i < vValue.size(); i++)
if (vfBest[i])
- printf("%s ", FormatMoney(vValue[i].first).c_str());
- printf("total %s\n", FormatMoney(nBest).c_str());
+ LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first).c_str());
+ LogPrint("selectcoins", "total %s\n", FormatMoney(nBest).c_str());
}
return true;
@@ -1336,7 +1335,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
{
LOCK2(cs_main, cs_wallet);
- printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
+ LogPrintf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
{
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
@@ -1372,7 +1371,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
if (!wtxNew.AcceptToMemoryPool(false))
{
// This must not fail. The transaction has already been signed and recorded.
- printf("CommitTransaction() : Error: Transaction not valid");
+ LogPrintf("CommitTransaction() : Error: Transaction not valid");
return false;
}
wtxNew.RelayWalletTransaction();
@@ -1391,7 +1390,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
if (IsLocked())
{
string strError = _("Error: Wallet locked, unable to create transaction!");
- printf("SendMoney() : %s", strError.c_str());
+ LogPrintf("SendMoney() : %s", strError.c_str());
return strError;
}
string strError;
@@ -1399,7 +1398,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
{
if (nValue + nFeeRequired > GetBalance())
strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired).c_str());
- printf("SendMoney() : %s\n", strError.c_str());
+ LogPrintf("SendMoney() : %s\n", strError.c_str());
return strError;
}
@@ -1461,7 +1460,11 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
{
std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
mapAddressBook[address].name = strName;
- NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
+ if (!strPurpose.empty()) /* update purpose only if requested */
+ mapAddressBook[address].purpose = strPurpose;
+ NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address),
+ mapAddressBook[address].purpose,
+ (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
if (!fFileBacked)
return false;
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
@@ -1472,7 +1475,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
bool CWallet::DelAddressBook(const CTxDestination& address)
{
mapAddressBook.erase(address);
- NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
+ NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
if (!fFileBacked)
return false;
CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
@@ -1486,10 +1489,10 @@ void CWallet::PrintWallet(const CBlock& block)
if (mapWallet.count(block.vtx[0].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
- printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
+ LogPrintf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
}
}
- printf("\n");
+ LogPrintf("\n");
}
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
@@ -1548,7 +1551,7 @@ bool CWallet::NewKeyPool()
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
setKeyPool.insert(nIndex);
}
- printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
+ LogPrintf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
}
return true;
}
@@ -1578,7 +1581,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
throw runtime_error("TopUpKeyPool() : writing generated key failed");
setKeyPool.insert(nEnd);
- printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
+ LogPrintf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
}
}
return true;
@@ -1607,7 +1610,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
if (!HaveKey(keypool.vchPubKey.GetID()))
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
assert(keypool.vchPubKey.IsValid());
- printf("keypool reserve %"PRI64d"\n", nIndex);
+ LogPrintf("keypool reserve %"PRI64d"\n", nIndex);
}
}
@@ -1634,7 +1637,7 @@ void CWallet::KeepKey(int64 nIndex)
CWalletDB walletdb(strWalletFile);
walletdb.ErasePool(nIndex);
}
- printf("keypool keep %"PRI64d"\n", nIndex);
+ LogPrintf("keypool keep %"PRI64d"\n", nIndex);
}
void CWallet::ReturnKey(int64 nIndex)
@@ -1644,7 +1647,7 @@ void CWallet::ReturnKey(int64 nIndex)
LOCK(cs_wallet);
setKeyPool.insert(nIndex);
}
- printf("keypool return %"PRI64d"\n", nIndex);
+ LogPrintf("keypool return %"PRI64d"\n", nIndex);
}
bool CWallet::GetKeyFromPool(CPubKey& result)
@@ -1832,7 +1835,7 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey)
vchPubKey = keypool.vchPubKey;
else {
if (pwallet->vchDefaultKey.IsValid()) {
- printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
+ LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
vchPubKey = pwallet->vchDefaultKey;
} else
return false;
@@ -1930,7 +1933,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
mapKeyBirth[it->first] = it->second.nCreateTime;
// map in which we'll infer heights of other keys
- CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
+ CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
std::set<CKeyID> setKeys;
GetKeys(setKeys);
@@ -1950,7 +1953,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
// iterate over all wallet transactions...
const CWalletTx &wtx = (*it).second;
std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
- if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
+ if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
// ... which are already in a block
int nHeight = blit->second->nHeight;
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
diff --git a/src/wallet.h b/src/wallet.h
index d61548433e..51bc9f67c4 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -335,12 +335,16 @@ public:
/** Address book entry changed.
* @note called with lock cs_wallet held.
*/
- boost::signals2::signal<void (CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status)> NotifyAddressBookChanged;
+ boost::signals2::signal<void (CWallet *wallet, const CTxDestination
+ &address, const std::string &label, bool isMine,
+ const std::string &purpose,
+ ChangeType status)> NotifyAddressBookChanged;
/** Wallet transaction added, removed or updated.
* @note called with lock cs_wallet held.
*/
- boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
+ boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
+ ChangeType status)> NotifyTransactionChanged;
};
/** A key allocated from the key pool. */
@@ -741,7 +745,7 @@ public:
void print() const
{
- printf("%s\n", ToString().c_str());
+ LogPrintf("%s\n", ToString().c_str());
}
};
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index d31db5e425..efcd59d5f1 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -271,8 +271,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
wss.fAnyUnordered = true;
//// debug print
- //printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
- //printf(" %12"PRI64d" %s %s %s\n",
+ //LogPrintf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
+ //LogPrintf(" %12"PRI64d" %s %s %s\n",
// wtx.vout[0].nValue,
// DateTimeStrFormat("%Y-%m-%d %H:%M:%S", wtx.GetBlockTime()).c_str(),
// wtx.hashBlock.ToString().c_str(),
@@ -479,7 +479,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
Dbc* pcursor = GetCursor();
if (!pcursor)
{
- printf("Error getting wallet database cursor\n");
+ LogPrintf("Error getting wallet database cursor\n");
return DB_CORRUPT;
}
@@ -493,7 +493,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
break;
else if (ret != 0)
{
- printf("Error reading next record from wallet database\n");
+ LogPrintf("Error reading next record from wallet database\n");
return DB_CORRUPT;
}
@@ -515,7 +515,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
}
}
if (!strErr.empty())
- printf("%s\n", strErr.c_str());
+ LogPrintf("%s\n", strErr.c_str());
}
pcursor->close();
}
@@ -534,9 +534,9 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (result != DB_LOAD_OK)
return result;
- printf("nFileVersion = %d\n", wss.nFileVersion);
+ LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
- printf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
+ LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
// nTimeFirstKey is only reliable if all keys have metadata
@@ -604,7 +604,7 @@ void ThreadFlushWalletDB(const string& strFile)
map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
if (mi != bitdb.mapFileUseCount.end())
{
- printf("Flushing wallet.dat\n");
+ LogPrint("db", "Flushing wallet.dat\n");
nLastFlushed = nWalletDBUpdated;
int64 nStart = GetTimeMillis();
@@ -613,7 +613,7 @@ void ThreadFlushWalletDB(const string& strFile)
bitdb.CheckpointLSN(strFile);
bitdb.mapFileUseCount.erase(mi++);
- printf("Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
+ LogPrint("db", "Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
}
}
}
@@ -648,10 +648,10 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
#else
filesystem::copy_file(pathSrc, pathDest);
#endif
- printf("copied wallet.dat to %s\n", pathDest.string().c_str());
+ LogPrintf("copied wallet.dat to %s\n", pathDest.string().c_str());
return true;
} catch(const filesystem::filesystem_error &e) {
- printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
+ LogPrintf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
return false;
}
}
@@ -679,10 +679,10 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL,
newFilename.c_str(), DB_AUTO_COMMIT);
if (result == 0)
- printf("Renamed %s to %s\n", filename.c_str(), newFilename.c_str());
+ LogPrintf("Renamed %s to %s\n", filename.c_str(), newFilename.c_str());
else
{
- printf("Failed to rename %s to %s\n", filename.c_str(), newFilename.c_str());
+ LogPrintf("Failed to rename %s to %s\n", filename.c_str(), newFilename.c_str());
return false;
}
@@ -690,10 +690,10 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
bool allOK = dbenv.Salvage(newFilename, true, salvagedData);
if (salvagedData.empty())
{
- printf("Salvage(aggressive) found no records in %s.\n", newFilename.c_str());
+ LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename.c_str());
return false;
}
- printf("Salvage(aggressive) found %"PRIszu" records\n", salvagedData.size());
+ LogPrintf("Salvage(aggressive) found %"PRIszu" records\n", salvagedData.size());
bool fSuccess = allOK;
Db* pdbCopy = new Db(&dbenv.dbenv, 0);
@@ -705,7 +705,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
0);
if (ret > 0)
{
- printf("Cannot create database file %s\n", filename.c_str());
+ LogPrintf("Cannot create database file %s\n", filename.c_str());
return false;
}
CWallet dummyWallet;
@@ -725,7 +725,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
continue;
if (!fReadOK)
{
- printf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType.c_str(), strErr.c_str());
+ LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType.c_str(), strErr.c_str());
continue;
}
}