aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac5
-rw-r--r--contrib/gitian-descriptors/deps-linux.yml10
-rw-r--r--contrib/gitian-descriptors/deps-win.yml10
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml6
-rw-r--r--contrib/gitian-descriptors/gitian-osx-bitcoin.yml8
-rw-r--r--contrib/gitian-descriptors/gitian-osx-depends.yml10
-rw-r--r--contrib/gitian-descriptors/gitian-osx-qt.yml6
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml6
-rw-r--r--contrib/gitian-descriptors/qt-linux.yml1
-rw-r--r--contrib/gitian-descriptors/qt-win.yml6
-rw-r--r--doc/release-notes.md19
-rw-r--r--doc/release-process.md14
-rw-r--r--doc/translation_process.md2
-rwxr-xr-xqa/rpc-tests/smartfees.py142
-rw-r--r--qa/rpc-tests/util.py174
-rw-r--r--src/Makefile.am81
-rw-r--r--src/Makefile.include79
-rw-r--r--src/Makefile.qt.include404
-rw-r--r--src/Makefile.qttest.include48
-rw-r--r--src/Makefile.test.include101
-rw-r--r--src/core.cpp19
-rw-r--r--src/core.h40
-rw-r--r--src/init.cpp37
-rw-r--r--src/init.h1
-rw-r--r--src/m4/bitcoin_qt.m42
-rw-r--r--src/main.cpp267
-rw-r--r--src/main.h17
-rw-r--r--src/miner.cpp66
-rw-r--r--src/net.cpp3
-rw-r--r--src/net.h1
-rw-r--r--src/qt/Makefile9
-rw-r--r--src/qt/Makefile.am382
-rw-r--r--src/qt/coincontroldialog.cpp29
-rw-r--r--src/qt/forms/rpcconsole.ui60
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/locale/bitcoin_el_GR.ts147
-rw-r--r--src/qt/locale/bitcoin_sl_SI.ts38
-rw-r--r--src/qt/locale/bitcoin_th_TH.ts96
-rw-r--r--src/qt/optionsdialog.cpp4
-rw-r--r--src/qt/optionsmodel.cpp21
-rw-r--r--src/qt/paymentserver.cpp2
-rw-r--r--src/qt/peertablemodel.cpp4
-rw-r--r--src/qt/rpcconsole.cpp12
-rw-r--r--src/qt/test/Makefile6
-rw-r--r--src/qt/test/Makefile.am46
-rw-r--r--src/qt/walletmodel.cpp6
-rw-r--r--src/rpcclient.cpp2
-rw-r--r--src/rpcmining.cpp61
-rw-r--r--src/rpcmisc.cpp4
-rw-r--r--src/rpcnet.cpp2
-rw-r--r--src/rpcserver.cpp4
-rw-r--r--src/rpcserver.h2
-rw-r--r--src/rpcwallet.cpp2
-rw-r--r--src/script.cpp11
-rw-r--r--src/test/Makefile6
-rw-r--r--src/test/Makefile.am77
-rw-r--r--src/txmempool.cpp370
-rw-r--r--src/txmempool.h23
-rw-r--r--src/util.cpp1
-rw-r--r--src/util.h1
-rw-r--r--src/wallet.cpp22
-rw-r--r--src/wallet.h23
62 files changed, 1952 insertions, 1108 deletions
diff --git a/configure.ac b/configure.ac
index 3a8d33a5a0..d8521ad3ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -666,6 +666,9 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet == xyes])
+AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests == xyes])
+AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt == xyes])
+AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$use_tests$bitcoin_enable_qt_test = xyesyes])
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])
@@ -695,7 +698,7 @@ AC_SUBST(LEVELDB_TARGET_FLAGS)
AC_SUBST(BUILD_TEST)
AC_SUBST(BUILD_QT)
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([Makefile src/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/gitian-descriptors/deps-linux.yml b/contrib/gitian-descriptors/deps-linux.yml
index af10461b83..8221222133 100644
--- a/contrib/gitian-descriptors/deps-linux.yml
+++ b/contrib/gitian-descriptors/deps-linux.yml
@@ -16,7 +16,7 @@ packages:
reference_datetime: "2013-06-01 00:00:00"
remotes: []
files:
-- "openssl-1.0.1g.tar.gz"
+- "openssl-1.0.1h.tar.gz"
- "miniupnpc-1.9.tar.gz"
- "qrencode-3.4.3.tar.bz2"
- "protobuf-2.5.0.tar.bz2"
@@ -30,15 +30,15 @@ script: |
export TZ=UTC
export LIBRARY_PATH="$STAGING/lib"
# Integrity Check
- echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c
+ echo "9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093 openssl-1.0.1h.tar.gz" | sha256sum -c
echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c
echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c
echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c
echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c
#
- tar xzf openssl-1.0.1g.tar.gz
- cd openssl-1.0.1g
+ tar xzf openssl-1.0.1h.tar.gz
+ cd openssl-1.0.1h
# need -fPIC to avoid relocation error in 64 bit builds
./config no-shared no-zlib no-dso no-krb5 --openssldir=$STAGING -fPIC
# need to build OpenSSL with faketime because a timestamp is embedded into cversion.o
@@ -95,4 +95,4 @@ script: |
done
#
cd $STAGING
- find include lib bin host | sort | zip -X@ $OUTDIR/bitcoin-deps-linux${GBUILD_BITS}-gitian-r5.zip
+ find include lib bin host | sort | zip -X@ $OUTDIR/bitcoin-deps-linux${GBUILD_BITS}-gitian-r6.zip
diff --git a/contrib/gitian-descriptors/deps-win.yml b/contrib/gitian-descriptors/deps-win.yml
index 17ac413d80..fabc2949eb 100644
--- a/contrib/gitian-descriptors/deps-win.yml
+++ b/contrib/gitian-descriptors/deps-win.yml
@@ -14,7 +14,7 @@ packages:
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
-- "openssl-1.0.1g.tar.gz"
+- "openssl-1.0.1h.tar.gz"
- "db-4.8.30.NC.tar.gz"
- "miniupnpc-1.9.tar.gz"
- "zlib-1.2.8.tar.gz"
@@ -28,7 +28,7 @@ script: |
INDIR=$HOME/build
TEMPDIR=$HOME/tmp
# Input Integrity Check
- echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c
+ echo "9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093 openssl-1.0.1h.tar.gz" | sha256sum -c
echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c
echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c
echo "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d zlib-1.2.8.tar.gz" | sha256sum -c
@@ -48,8 +48,8 @@ script: |
mkdir -p $INSTALLPREFIX $BUILDDIR
cd $BUILDDIR
#
- tar xzf $INDIR/openssl-1.0.1g.tar.gz
- cd openssl-1.0.1g
+ tar xzf $INDIR/openssl-1.0.1h.tar.gz
+ cd openssl-1.0.1h
if [ "$BITS" == "32" ]; then
OPENSSL_TGT=mingw
else
@@ -124,5 +124,5 @@ script: |
done
#
cd $INSTALLPREFIX
- find include lib | sort | zip -X@ $OUTDIR/bitcoin-deps-win$BITS-gitian-r12.zip
+ find include lib | sort | zip -X@ $OUTDIR/bitcoin-deps-win$BITS-gitian-r13.zip
done # for BITS in
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index bb59e1cecb..65a6c3c1e9 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -25,8 +25,8 @@ remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
files:
-- "bitcoin-deps-linux32-gitian-r5.zip"
-- "bitcoin-deps-linux64-gitian-r5.zip"
+- "bitcoin-deps-linux32-gitian-r6.zip"
+- "bitcoin-deps-linux64-gitian-r6.zip"
- "boost-linux32-1.55.0-gitian-r1.zip"
- "boost-linux64-1.55.0-gitian-r1.zip"
- "qt-linux32-4.6.4-gitian-r1.tar.gz"
@@ -43,7 +43,7 @@ script: |
#
mkdir -p $STAGING
cd $STAGING
- unzip ../build/bitcoin-deps-linux${GBUILD_BITS}-gitian-r5.zip
+ unzip ../build/bitcoin-deps-linux${GBUILD_BITS}-gitian-r6.zip
unzip ../build/boost-linux${GBUILD_BITS}-1.55.0-gitian-r1.zip
tar -zxf ../build/qt-linux${GBUILD_BITS}-4.6.4-gitian-r1.tar.gz
cd ../build
diff --git a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml
index e29047d610..44b5de9be3 100644
--- a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml
+++ b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml
@@ -18,8 +18,8 @@ remotes:
"dir": "bitcoin"
files:
- "osx-native-depends-r3.tar.gz"
-- "osx-depends-r3.tar.gz"
-- "osx-depends-qt-5.2.1-r3.tar.gz"
+- "osx-depends-r4.tar.gz"
+- "osx-depends-qt-5.2.1-r4.tar.gz"
- "MacOSX10.7.sdk.tar.gz"
script: |
@@ -37,8 +37,8 @@ script: |
tar -C osx-cross-depends/SDKs -xf ${SOURCES_PATH}/MacOSX10.7.sdk.tar.gz
tar -C osx-cross-depends -xf osx-native-depends-r3.tar.gz
- tar -C osx-cross-depends -xf osx-depends-r3.tar.gz
- tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r3.tar.gz
+ tar -C osx-cross-depends -xf osx-depends-r4.tar.gz
+ tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r4.tar.gz
export PATH=`pwd`/osx-cross-depends/native-prefix/bin:$PATH
cd bitcoin
diff --git a/contrib/gitian-descriptors/gitian-osx-depends.yml b/contrib/gitian-descriptors/gitian-osx-depends.yml
index adc86e5cb4..07a021cf0c 100644
--- a/contrib/gitian-descriptors/gitian-osx-depends.yml
+++ b/contrib/gitian-descriptors/gitian-osx-depends.yml
@@ -15,7 +15,7 @@ files:
- "boost_1_55_0.tar.bz2"
- "db-4.8.30.NC.tar.gz"
- "miniupnpc-1.9.tar.gz"
-- "openssl-1.0.1g.tar.gz"
+- "openssl-1.0.1h.tar.gz"
- "protobuf-2.5.0.tar.bz2"
- "qrencode-3.4.3.tar.bz2"
- "MacOSX10.7.sdk.tar.gz"
@@ -26,11 +26,11 @@ script: |
echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | sha256sum -c
echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c
echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c
- echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c
+ echo "9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093 openssl-1.0.1h.tar.gz" | sha256sum -c
echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c
echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c
- REVISION=r3
+ REVISION=r4
export SOURCES_PATH=`pwd`
export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME""
export PATH=$HOME:$PATH
@@ -88,8 +88,8 @@ script: |
popd
# openssl
- SOURCE_FILE=${SOURCES_PATH}/openssl-1.0.1g.tar.gz
- BUILD_DIR=${BUILD_BASE}/openssl-1.0.1g
+ SOURCE_FILE=${SOURCES_PATH}/openssl-1.0.1h.tar.gz
+ BUILD_DIR=${BUILD_BASE}/openssl-1.0.1h
tar -C ${BUILD_BASE} -xf ${SOURCE_FILE}
pushd ${BUILD_DIR}
diff --git a/contrib/gitian-descriptors/gitian-osx-qt.yml b/contrib/gitian-descriptors/gitian-osx-qt.yml
index b57908dbd9..5e0ad9222a 100644
--- a/contrib/gitian-descriptors/gitian-osx-qt.yml
+++ b/contrib/gitian-descriptors/gitian-osx-qt.yml
@@ -14,14 +14,14 @@ remotes: []
files:
- "qt-everywhere-opensource-src-5.2.1.tar.gz"
- "osx-native-depends-r3.tar.gz"
-- "osx-depends-r3.tar.gz"
+- "osx-depends-r4.tar.gz"
- "MacOSX10.7.sdk.tar.gz"
script: |
echo "84e924181d4ad6db00239d87250cc89868484a14841f77fb85ab1f1dbdcd7da1 qt-everywhere-opensource-src-5.2.1.tar.gz" | sha256sum -c
- REVISION=r3
+ REVISION=r4
export SOURCES_PATH=`pwd`
export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME""
export ZERO_AR_DATE=1
@@ -73,7 +73,7 @@ script: |
tar xf /home/ubuntu/build/osx-native-depends-r3.tar.gz
export PATH=`pwd`/native-prefix/bin:$PATH
- tar xf /home/ubuntu/build/osx-depends-r3.tar.gz
+ tar xf /home/ubuntu/build/osx-depends-r4.tar.gz
SOURCE_FILE=${SOURCES_PATH}/qt-everywhere-opensource-src-5.2.1.tar.gz
BUILD_DIR=${BUILD_BASE}/qt-everywhere-opensource-src-5.2.1
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index 2191fb36c7..245f15ccab 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -26,8 +26,8 @@ files:
- "qt-win64-5.2.0-gitian-r3.zip"
- "boost-win32-1.55.0-gitian-r6.zip"
- "boost-win64-1.55.0-gitian-r6.zip"
-- "bitcoin-deps-win32-gitian-r12.zip"
-- "bitcoin-deps-win64-gitian-r12.zip"
+- "bitcoin-deps-win32-gitian-r13.zip"
+- "bitcoin-deps-win64-gitian-r13.zip"
- "protobuf-win32-2.5.0-gitian-r4.zip"
- "protobuf-win64-2.5.0-gitian-r4.zip"
script: |
@@ -61,7 +61,7 @@ script: |
cd $STAGING
unzip $INDIR/qt-win${BITS}-5.2.0-gitian-r3.zip
unzip $INDIR/boost-win${BITS}-1.55.0-gitian-r6.zip
- unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r12.zip
+ unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r13.zip
unzip $INDIR/protobuf-win${BITS}-2.5.0-gitian-r4.zip
if [ "$NEEDDIST" == "1" ]; then
# Make source code archive which is architecture independent so it only needs to be done once
diff --git a/contrib/gitian-descriptors/qt-linux.yml b/contrib/gitian-descriptors/qt-linux.yml
index 1462df3289..b163b4bb8c 100644
--- a/contrib/gitian-descriptors/qt-linux.yml
+++ b/contrib/gitian-descriptors/qt-linux.yml
@@ -40,6 +40,7 @@ script: |
tar xzf qt-everywhere-opensource-src-4.6.4.tar.gz
cd qt-everywhere-opensource-src-4.6.4
QTBUILDDIR=$(pwd)
+ sed 's/TODAY=`date +%Y-%m-%d`/TODAY=2011-01-30/' -i configure
# Need to build 4.6-versioned host utilities as well (lrelease/qrc/lupdate/...)
./configure -prefix $INSTALLPREFIX -confirm-license -release -opensource -no-qt3support -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
diff --git a/contrib/gitian-descriptors/qt-win.yml b/contrib/gitian-descriptors/qt-win.yml
index 8f24492b53..7000c70051 100644
--- a/contrib/gitian-descriptors/qt-win.yml
+++ b/contrib/gitian-descriptors/qt-win.yml
@@ -15,8 +15,8 @@ reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
- "qt-everywhere-opensource-src-5.2.0.tar.gz"
-- "bitcoin-deps-win32-gitian-r12.zip"
-- "bitcoin-deps-win64-gitian-r12.zip"
+- "bitcoin-deps-win32-gitian-r13.zip"
+- "bitcoin-deps-win64-gitian-r13.zip"
script: |
# Defines
export TZ=UTC
@@ -48,7 +48,7 @@ script: |
#
# Need mingw-compiled openssl from bitcoin-deps:
cd $DEPSDIR
- unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r12.zip
+ unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r13.zip
#
cd $BUILDDIR
#
diff --git a/doc/release-notes.md b/doc/release-notes.md
index f16eec32a2..9272d427cd 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,2 +1,21 @@
(note: this is a temporary file, to be added-to by anybody, and moved to
release-notes at release time)
+
+New RPC methods
+===============
+
+Fee/Priority estimation
+-----------------------
+
+estimatefee nblocks : Returns approximate fee-per-1,000-bytes needed for
+a transaction to be confirmed within nblocks. Returns -1 if not enough
+transactions have been observed to compute a good estimate.
+
+estimatepriority nblocks : Returns approximate priority needed for
+a zero-fee transaction to confirm within nblocks. Returns -1 if not
+enough free transactions have been observed to compute a good
+estimate.
+
+Statistics used to estimate fees and priorities are saved in the
+data directory in the 'fee_estimates.dat' file just before
+program shutdown, and are read in at startup.
diff --git a/doc/release-process.md b/doc/release-process.md
index 6d08c48496..5b96e53753 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -44,7 +44,7 @@ Release Process
Fetch and build inputs: (first time, or when dependency versions change)
wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.9.tar.gz' -O miniupnpc-1.9.tar.gz
- wget 'https://www.openssl.org/source/openssl-1.0.1g.tar.gz'
+ wget 'https://www.openssl.org/source/openssl-1.0.1h.tar.gz'
wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
wget 'http://zlib.net/zlib-1.2.8.tar.gz'
wget 'ftp://ftp.simplesystems.org/pub/png/src/history/libpng16/libpng-1.6.8.tar.gz'
@@ -89,16 +89,16 @@ Release Process
The expected SHA256 hashes of the intermediate inputs are:
- 35c3dfd8b9362f59e81b51881b295232e3bc9e286f1add193b59d486d9ac4a5c bitcoin-deps-linux32-gitian-r5.zip
- 571789867d172500fa96d63d0ba8c5b1e1a3d6f44f720eddf2f93665affc88b3 bitcoin-deps-linux64-gitian-r5.zip
+ 46710f673467e367738d8806e45b4cb5931aaeea61f4b6b55a68eea56d5006c5 bitcoin-deps-linux32-gitian-r6.zip
+ f03be39fb26670243d3a659e64d18e19d03dec5c11e9912011107768390b5268 bitcoin-deps-linux64-gitian-r6.zip
f29b7d9577417333fb56e023c2977f5726a7c297f320b175a4108cf7cd4c2d29 boost-linux32-1.55.0-gitian-r1.zip
88232451c4104f7eb16e469ac6474fd1231bd485687253f7b2bdf46c0781d535 boost-linux64-1.55.0-gitian-r1.zip
- 74ec2d301cf1a9d03b194153f545102ba45dad02b390485212fe6717de486361 qt-linux32-4.6.4-gitian-r1.tar.gz
- 01d0477e299467f09280f15424781154e2b1ea4072c5edb16e044c234954fd9a qt-linux64-4.6.4-gitian-r1.tar.gz
+ 57e57dbdadc818cd270e7e00500a5e1085b3bcbdef69a885f0fb7573a8d987e1 qt-linux32-4.6.4-gitian-r1.tar.gz
+ 60eb4b9c5779580b7d66529efa5b2836ba1a70edde2a0f3f696d647906a826be qt-linux64-4.6.4-gitian-r1.tar.gz
60dc2d3b61e9c7d5dbe2f90d5955772ad748a47918ff2d8b74e8db9b1b91c909 boost-win32-1.55.0-gitian-r6.zip
f65fcaf346bc7b73bc8db3a8614f4f6bee2f61fcbe495e9881133a7c2612a167 boost-win64-1.55.0-gitian-r6.zip
- 97e62002d338885336bb24e7cbb9471491294bd8857af7a83d18c0961f864ec0 bitcoin-deps-win32-gitian-r11.zip
- ee3ea2d5aac1a67ea6bfbea2c04068a7c0940616ce48ee4f37c264bb9d4438ef bitcoin-deps-win64-gitian-r11.zip
+ 70de248cd0dd7e7476194129e818402e974ca9c5751cbf591644dc9f332d3b59 bitcoin-deps-win32-gitian-r13.zip
+ 9eace4c76f639f4f3580a478eee4f50246e1bbb5ccdcf37a158261a5a3fa3e65 bitcoin-deps-win64-gitian-r13.zip
963e3e5e85879010a91143c90a711a5d1d5aba992e38672cdf7b54e42c56b2f1 qt-win32-5.2.0-gitian-r3.zip
751c579830d173ef3e6f194e83d18b92ebef6df03289db13ab77a52b6bc86ef0 qt-win64-5.2.0-gitian-r3.zip
e2e403e1a08869c7eed4d4293bce13d51ec6a63592918b90ae215a0eceb44cb4 protobuf-win32-2.5.0-gitian-r4.zip
diff --git a/doc/translation_process.md b/doc/translation_process.md
index 2f0845a877..61a0a0ffed 100644
--- a/doc/translation_process.md
+++ b/doc/translation_process.md
@@ -1,7 +1,7 @@
Translations
============
-The Qt GUI can be easily translated into other languages. Here's how we
+The Bitcoin Core GUI can be easily translated into other languages. Here's how we
handle those translations.
Files and Folders
diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py
new file mode 100755
index 0000000000..e8abbfba19
--- /dev/null
+++ b/qa/rpc-tests/smartfees.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+
+#
+# Test fee estimation code
+#
+
+# Add python-bitcoinrpc to module search path:
+import os
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
+
+import json
+import random
+import shutil
+import subprocess
+import tempfile
+import traceback
+
+from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from util import *
+
+
+def run_test(nodes, test_dir):
+ nodes.append(start_node(0, test_dir,
+ ["-debug=mempool", "-debug=estimatefee"]))
+ # Node1 mines small-but-not-tiny blocks, and allows free transactions.
+ # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
+ # so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for
+ # 6 or 7 transactions)
+ nodes.append(start_node(1, test_dir,
+ ["-blockprioritysize=1500", "-blockmaxsize=2000",
+ "-debug=mempool", "-debug=estimatefee"]))
+ connect_nodes(nodes[1], 0)
+
+ # Node2 is a stingy miner, that
+ # produces very small blocks (room for only 3 or so transactions)
+ node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
+ "-debug=mempool", "-debug=estimatefee"]
+ nodes.append(start_node(2, test_dir, node2args))
+ connect_nodes(nodes[2], 0)
+
+ sync_blocks(nodes)
+
+ # Prime the memory pool with pairs of transactions
+ # (high-priority, random fee and zero-priority, random fee)
+ min_fee = Decimal("0.001")
+ fees_per_kb = [];
+ for i in range(12):
+ (txid, txhex, fee) = random_zeropri_transaction(nodes, Decimal("1.1"),
+ min_fee, min_fee, 20)
+ tx_kbytes = (len(txhex)/2)/1000.0
+ fees_per_kb.append(float(fee)/tx_kbytes)
+
+ # Mine blocks with node2 until the memory pool clears:
+ count_start = nodes[2].getblockcount()
+ while len(nodes[2].getrawmempool()) > 0:
+ nodes[2].setgenerate(True, 1)
+ sync_blocks(nodes)
+
+ all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
+ print("Fee estimates, super-stingy miner: "+str([str(e) for e in all_estimates]))
+
+ # Estimates should be within the bounds of what transactions fees actually were:
+ delta = 1.0e-6 # account for rounding error
+ for e in filter(lambda x: x >= 0, all_estimates):
+ if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
+ raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
+
+ # Generate transactions while mining 30 more blocks, this time with node1:
+ for i in range(30):
+ for j in range(random.randrange(6-4,6+4)):
+ (txid, txhex, fee) = random_transaction(nodes, Decimal("1.1"),
+ Decimal("0.0"), min_fee, 20)
+ tx_kbytes = (len(txhex)/2)/1000.0
+ fees_per_kb.append(float(fee)/tx_kbytes)
+ nodes[1].setgenerate(True, 1)
+ sync_blocks(nodes)
+
+ all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
+ print("Fee estimates, more generous miner: "+str([ str(e) for e in all_estimates]))
+ for e in filter(lambda x: x >= 0, all_estimates):
+ if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
+ raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
+
+ # Finish by mining a normal-sized block:
+ while len(nodes[0].getrawmempool()) > 0:
+ nodes[0].setgenerate(True, 1)
+ sync_blocks(nodes)
+
+ final_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
+ print("Final fee estimates: "+str([ str(e) for e in final_estimates]))
+
+def main():
+ import optparse
+
+ parser = optparse.OptionParser(usage="%prog [options]")
+ parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
+ help="Leave bitcoinds and test.* datadir on exit or error")
+ parser.add_option("--srcdir", dest="srcdir", default="../../src",
+ help="Source directory containing bitcoind/bitcoin-cli (default: %default%)")
+ parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
+ help="Root directory for datadirs")
+ (options, args) = parser.parse_args()
+
+ os.environ['PATH'] = options.srcdir+":"+os.environ['PATH']
+
+ check_json_precision()
+
+ success = False
+ nodes = []
+ try:
+ print("Initializing test directory "+options.tmpdir)
+ print(" node0 running at: 127.0.0.1:%d"%(p2p_port(0)))
+ if not os.path.isdir(options.tmpdir):
+ os.makedirs(options.tmpdir)
+ initialize_chain(options.tmpdir)
+
+ run_test(nodes, options.tmpdir)
+
+ success = True
+
+ except AssertionError as e:
+ print("Assertion failed: "+e.message)
+ except Exception as e:
+ print("Unexpected exception caught during testing: "+str(e))
+ traceback.print_tb(sys.exc_info()[2])
+
+ if not options.nocleanup:
+ print("Cleaning up")
+ stop_nodes(nodes)
+ wait_bitcoinds()
+ shutil.rmtree(options.tmpdir)
+
+ if success:
+ print("Tests successful")
+ sys.exit(0)
+ else:
+ print("Failed")
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py
index 40f4a1458f..eded098c7c 100644
--- a/qa/rpc-tests/util.py
+++ b/qa/rpc-tests/util.py
@@ -12,6 +12,7 @@ sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python
from decimal import Decimal
import json
+import random
import shutil
import subprocess
import time
@@ -20,8 +21,10 @@ import re
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from util import *
-START_P2P_PORT=11000
-START_RPC_PORT=11100
+def p2p_port(n):
+ return 11000 + n + os.getpid()%999
+def rpc_port(n):
+ return 12000 + n + os.getpid()%999
def check_json_precision():
"""Make sure json library being used does not lose precision converting BTC values"""
@@ -58,6 +61,18 @@ def sync_mempools(rpc_connections):
bitcoind_processes = []
+def initialize_datadir(dir, n):
+ datadir = os.path.join(dir, "node"+str(n))
+ if not os.path.isdir(datadir):
+ os.makedirs(datadir)
+ with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f:
+ f.write("regtest=1\n");
+ f.write("rpcuser=rt\n");
+ f.write("rpcpassword=rt\n");
+ f.write("port="+str(p2p_port(n))+"\n");
+ f.write("rpcport="+str(rpc_port(n))+"\n");
+ return datadir
+
def initialize_chain(test_dir):
"""
Create (or copy from cache) a 200-block-long chain and
@@ -69,17 +84,10 @@ def initialize_chain(test_dir):
devnull = open("/dev/null", "w+")
# Create cache directories, run bitcoinds:
for i in range(4):
- datadir = os.path.join("cache", "node"+str(i))
- os.makedirs(datadir)
- with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f:
- f.write("regtest=1\n");
- f.write("rpcuser=rt\n");
- f.write("rpcpassword=rt\n");
- f.write("port="+str(START_P2P_PORT+i)+"\n");
- f.write("rpcport="+str(START_RPC_PORT+i)+"\n");
+ datadir=initialize_datadir("cache", i)
args = [ "bitcoind", "-keypool=1", "-datadir="+datadir ]
if i > 0:
- args.append("-connect=127.0.0.1:"+str(START_P2P_PORT))
+ args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
bitcoind_processes.append(subprocess.Popen(args))
subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir,
"-rpcwait", "getblockcount"], stdout=devnull)
@@ -87,7 +95,7 @@ def initialize_chain(test_dir):
rpcs = []
for i in range(4):
try:
- url = "http://rt:rt@127.0.0.1:%d"%(START_RPC_PORT+i,)
+ url = "http://rt:rt@127.0.0.1:%d"%(rpc_port(i),)
rpcs.append(AuthServiceProxy(url))
except:
sys.stderr.write("Error connecting to "+url+"\n")
@@ -112,6 +120,7 @@ def initialize_chain(test_dir):
from_dir = os.path.join("cache", "node"+str(i))
to_dir = os.path.join(test_dir, "node"+str(i))
shutil.copytree(from_dir, to_dir)
+ initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf
def _rpchost_to_args(rpchost):
'''Convert optional IP:port spec to rpcconnect/rpcport args'''
@@ -133,25 +142,28 @@ def _rpchost_to_args(rpchost):
rv += ['-rpcport=' + rpcport]
return rv
-def start_nodes(num_nodes, dir, extra_args=None, rpchost=None):
- # Start bitcoinds, and wait for RPC interface to be up and running:
+def start_node(i, dir, extra_args=None, rpchost=None):
+ """
+ Start a bitcoind and return RPC connection to it
+ """
+ datadir = os.path.join(dir, "node"+str(i))
+ args = [ "bitcoind", "-datadir="+datadir, "-keypool=1" ]
+ if extra_args is not None: args.extend(extra_args)
+ bitcoind_processes.append(subprocess.Popen(args))
devnull = open("/dev/null", "w+")
- for i in range(num_nodes):
- datadir = os.path.join(dir, "node"+str(i))
- args = [ "bitcoind", "-datadir="+datadir ]
- if extra_args is not None:
- args += extra_args[i]
- bitcoind_processes.append(subprocess.Popen(args))
- subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir] +
- _rpchost_to_args(rpchost) +
- ["-rpcwait", "getblockcount"], stdout=devnull)
+ subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir] +
+ _rpchost_to_args(rpchost) +
+ ["-rpcwait", "getblockcount"], stdout=devnull)
devnull.close()
- # Create&return JSON-RPC connections
- rpc_connections = []
- for i in range(num_nodes):
- url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', START_RPC_PORT+i,)
- rpc_connections.append(AuthServiceProxy(url))
- return rpc_connections
+ url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
+ return AuthServiceProxy(url)
+
+def start_nodes(num_nodes, dir, extra_args=None, rpchost=None):
+ """
+ Start multiple bitcoinds, return RPC connections to them
+ """
+ if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
+ return [ start_node(i, dir, extra_args[i], rpchost) for i in range(num_nodes) ]
def debug_log(dir, n_node):
return os.path.join(dir, "node"+str(n_node), "regtest", "debug.log")
@@ -168,9 +180,111 @@ def wait_bitcoinds():
del bitcoind_processes[:]
def connect_nodes(from_connection, node_num):
- ip_port = "127.0.0.1:"+str(START_P2P_PORT+node_num)
+ ip_port = "127.0.0.1:"+str(p2p_port(node_num))
from_connection.addnode(ip_port, "onetry")
+def find_output(node, txid, amount):
+ """
+ Return index to output of txid with value amount
+ Raises exception if there is none.
+ """
+ txdata = node.getrawtransaction(txid, 1)
+ for i in range(len(txdata["vout"])):
+ if txdata["vout"][i]["value"] == amount:
+ return i
+ raise RuntimeError("find_output txid %s : %s not found"%(txid,str(amount)))
+
+def gather_inputs(from_node, amount_needed):
+ """
+ Return a random set of unspent txouts that are enough to pay amount_needed
+ """
+ utxo = from_node.listunspent(1)
+ random.shuffle(utxo)
+ inputs = []
+ total_in = Decimal("0.00000000")
+ while total_in < amount_needed and len(utxo) > 0:
+ t = utxo.pop()
+ total_in += t["amount"]
+ inputs.append({ "txid" : t["txid"], "vout" : t["vout"], "address" : t["address"] } )
+ if total_in < amount_needed:
+ raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee*2, total_in))
+ return (total_in, inputs)
+
+def make_change(from_node, amount_in, amount_out, fee):
+ """
+ Create change output(s), return them
+ """
+ outputs = {}
+ amount = amount_out+fee
+ change = amount_in - amount
+ if change > amount*2:
+ # Create an extra change output to break up big inputs
+ outputs[from_node.getnewaddress()] = float(change/2)
+ change = change/2
+ if change > 0:
+ outputs[from_node.getnewaddress()] = float(change)
+ return outputs
+
+def send_zeropri_transaction(from_node, to_node, amount, fee):
+ """
+ Create&broadcast a zero-priority transaction.
+ Returns (txid, hex-encoded-txdata)
+ Ensures transaction is zero-priority by first creating a send-to-self,
+ then using it's output
+ """
+
+ # Create a send-to-self with confirmed inputs:
+ self_address = from_node.getnewaddress()
+ (total_in, inputs) = gather_inputs(from_node, amount+fee*2)
+ outputs = make_change(from_node, total_in, amount+fee, fee)
+ outputs[self_address] = float(amount+fee)
+
+ self_rawtx = from_node.createrawtransaction(inputs, outputs)
+ self_signresult = from_node.signrawtransaction(self_rawtx)
+ self_txid = from_node.sendrawtransaction(self_signresult["hex"], True)
+
+ vout = find_output(from_node, self_txid, amount+fee)
+ # Now immediately spend the output to create a 1-input, 1-output
+ # zero-priority transaction:
+ inputs = [ { "txid" : self_txid, "vout" : vout } ]
+ outputs = { to_node.getnewaddress() : float(amount) }
+
+ rawtx = from_node.createrawtransaction(inputs, outputs)
+ signresult = from_node.signrawtransaction(rawtx)
+ txid = from_node.sendrawtransaction(signresult["hex"], True)
+
+ return (txid, signresult["hex"])
+
+def random_zeropri_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
+ """
+ Create a random zero-priority transaction.
+ Returns (txid, hex-encoded-transaction-data, fee)
+ """
+ from_node = random.choice(nodes)
+ to_node = random.choice(nodes)
+ fee = min_fee + fee_increment*random.randint(0,fee_variants)
+ (txid, txhex) = send_zeropri_transaction(from_node, to_node, amount, fee)
+ return (txid, txhex, fee)
+
+def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
+ """
+ Create a random transaction.
+ Returns (txid, hex-encoded-transaction-data, fee)
+ """
+ from_node = random.choice(nodes)
+ to_node = random.choice(nodes)
+ fee = min_fee + fee_increment*random.randint(0,fee_variants)
+
+ (total_in, inputs) = gather_inputs(from_node, amount+fee)
+ outputs = make_change(from_node, total_in, amount, fee)
+ outputs[to_node.getnewaddress()] = float(amount)
+
+ rawtx = from_node.createrawtransaction(inputs, outputs)
+ signresult = from_node.signrawtransaction(rawtx)
+ txid = from_node.sendrawtransaction(signresult["hex"], True)
+
+ return (txid, signresult["hex"], fee)
+
def assert_equal(thing1, thing2):
if thing1 != thing2:
raise AssertionError("%s != %s"%(str(thing1),str(thing2)))
diff --git a/src/Makefile.am b/src/Makefile.am
index a49ad58716..3016be47b9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,16 +1,35 @@
-include Makefile.include
+AM_CPPFLAGS = $(INCLUDES)
+AM_LDFLAGS = $(PTHREAD_CFLAGS)
-AM_CPPFLAGS += -I$(builddir)
+
+if EMBEDDED_LEVELDB
+LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
+LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
+LIBLEVELDB += $(builddir)/leveldb/libleveldb.a
+LIBMEMENV += $(builddir)/leveldb/libmemenv.a
+
+# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race
+$(LIBLEVELDB): $(LIBMEMENV)
+
+$(LIBLEVELDB) $(LIBMEMENV):
+ @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
+ CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
+ OPT="$(CXXFLAGS) $(CPPFLAGS)"
+endif
+
+BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS)
noinst_LIBRARIES = \
libbitcoin_server.a \
libbitcoin_common.a \
libbitcoin_cli.a
if ENABLE_WALLET
+BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
noinst_LIBRARIES += libbitcoin_wallet.a
endif
bin_PROGRAMS =
+TESTS =
if BUILD_BITCOIND
bin_PROGRAMS += bitcoind
@@ -20,8 +39,6 @@ if BUILD_BITCOIN_CLI
bin_PROGRAMS += bitcoin-cli
endif
-SUBDIRS = . $(BUILD_QT) $(BUILD_TEST)
-DIST_SUBDIRS = . qt test
.PHONY: FORCE
# bitcoin core #
BITCOIN_CORE_H = \
@@ -82,11 +99,12 @@ JSON_H = \
json/json_spirit_writer_template.h
obj/build.h: FORCE
- @$(MKDIR_P) $(abs_top_builddir)/src/obj
+ @$(MKDIR_P) $(builddir)/obj
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
$(abs_top_srcdir)
-version.o: obj/build.h
+libbitcoin_common_a-version.$(OBJEXT): obj/build.h
+libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_server_a_SOURCES = \
addrman.cpp \
alert.cpp \
@@ -111,6 +129,7 @@ libbitcoin_server_a_SOURCES = \
$(JSON_H) \
$(BITCOIN_CORE_H)
+libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_wallet_a_SOURCES = \
db.cpp \
crypter.cpp \
@@ -120,6 +139,7 @@ libbitcoin_wallet_a_SOURCES = \
walletdb.cpp \
$(BITCOIN_CORE_H)
+libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_common_a_SOURCES = \
base58.cpp \
allocators.cpp \
@@ -145,7 +165,7 @@ libbitcoin_cli_a_SOURCES = \
rpcclient.cpp \
$(BITCOIN_CORE_H)
-nodist_libbitcoin_common_a_SOURCES = $(top_srcdir)/src/obj/build.h
+nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h
#
# bitcoind binary #
@@ -165,8 +185,8 @@ if TARGET_WINDOWS
bitcoind_SOURCES += bitcoind-res.rc
endif
-AM_CPPFLAGS += $(BDB_CPPFLAGS)
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS)
+bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
# bitcoin-cli binary #
bitcoin_cli_LDADD = \
@@ -174,30 +194,49 @@ bitcoin_cli_LDADD = \
libbitcoin_common.a \
$(BOOST_LIBS)
bitcoin_cli_SOURCES = bitcoin-cli.cpp
+bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
#
if TARGET_WINDOWS
bitcoin_cli_SOURCES += bitcoin-cli-res.rc
endif
-# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race
-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_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_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
+EXTRA_DIST = leveldb
clean-local:
-$(MAKE) -C leveldb clean
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
+
+.rc.o:
+ @test -f $(WINDRES)
+ $(AM_V_GEN) $(WINDRES) -i $< -o $@
+
+.mm.o:
+ $(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $<
+
+%.pb.cc %.pb.h: %.proto
+ @test -f $(PROTOC)
+ $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
+
+LIBBITCOIN_SERVER=libbitcoin_server.a
+LIBBITCOIN_WALLET=libbitcoin_wallet.a
+LIBBITCOIN_COMMON=libbitcoin_common.a
+LIBBITCOIN_CLI=libbitcoin_cli.a
+LIBBITCOINQT=qt/libbitcoinqt.a
+
+if ENABLE_TESTS
+include Makefile.test.include
+endif
+
+if ENABLE_QT
+include Makefile.qt.include
+endif
+
+if ENABLE_QT_TESTS
+include Makefile.qttest.include
+endif
diff --git a/src/Makefile.include b/src/Makefile.include
deleted file mode 100644
index 2fc6cd7775..0000000000
--- a/src/Makefile.include
+++ /dev/null
@@ -1,79 +0,0 @@
-if EMBEDDED_LEVELDB
-LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/include
-LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv
-LIBLEVELDB += $(top_builddir)/src/leveldb/libleveldb.a
-LIBMEMENV += $(top_builddir)/src/leveldb/libmemenv.a
-endif
-
-AM_CPPFLAGS = $(INCLUDES) \
- -I$(top_builddir)/src/obj \
- $(BDB_CPPFLAGS) \
- $(BOOST_CPPFLAGS) $(BOOST_INCLUDES)
-AM_CPPFLAGS += $(LEVELDB_CPPFLAGS)
-AM_LDFLAGS = $(PTHREAD_CFLAGS)
-
-LIBBITCOIN_SERVER=$(top_builddir)/src/libbitcoin_server.a
-LIBBITCOIN_WALLET=$(top_builddir)/src/libbitcoin_wallet.a
-LIBBITCOIN_COMMON=$(top_builddir)/src/libbitcoin_common.a
-LIBBITCOIN_CLI=$(top_builddir)/src/libbitcoin_cli.a
-LIBBITCOINQT=$(top_builddir)/src/qt/libbitcoinqt.a
-
-$(LIBBITCOIN):
- $(MAKE) -C $(top_builddir)/src $(@F)
-
-if EMBEDDED_LEVELDB
-$(LIBLEVELDB) $(LIBMEMENV):
- $(MAKE) -C $(top_builddir)/src leveldb/$(@F)
-endif
-
-$(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) && QT_SELECT=$(QT_SELECT) $(UIC) -o $(abs_builddir)/$@ $(abs_srcdir)/$< || echo error: could not build $(abs_builddir)/$@
- $(SED) -e '/^\*\*.*Created:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,}
- $(SED) -e '/^\*\*.*by:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,}
-
-%.moc: %.cpp
- QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $<
- $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,}
- $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,}
-
-moc_%.cpp: %.h
- QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $<
- $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,}
- $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,}
-
-%.qm: %.ts
- @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D)
- @test -f $(LRELEASE) && QT_SELECT=$(QT_SELECT) $(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/Makefile.qt.include b/src/Makefile.qt.include
new file mode 100644
index 0000000000..749b976c44
--- /dev/null
+++ b/src/Makefile.qt.include
@@ -0,0 +1,404 @@
+bin_PROGRAMS += qt/bitcoin-qt
+noinst_LIBRARIES += qt/libbitcoinqt.a
+
+# bitcoin qt core #
+QT_TS = \
+ qt/locale/bitcoin_ach.ts \
+ qt/locale/bitcoin_af_ZA.ts \
+ qt/locale/bitcoin_ar.ts \
+ qt/locale/bitcoin_be_BY.ts \
+ qt/locale/bitcoin_bg.ts \
+ qt/locale/bitcoin_bs.ts \
+ qt/locale/bitcoin_ca_ES.ts \
+ qt/locale/bitcoin_ca.ts \
+ qt/locale/bitcoin_ca@valencia.ts \
+ qt/locale/bitcoin_cmn.ts \
+ qt/locale/bitcoin_cs.ts \
+ qt/locale/bitcoin_cy.ts \
+ qt/locale/bitcoin_da.ts \
+ qt/locale/bitcoin_de.ts \
+ qt/locale/bitcoin_el_GR.ts \
+ qt/locale/bitcoin_en.ts \
+ qt/locale/bitcoin_eo.ts \
+ qt/locale/bitcoin_es_CL.ts \
+ qt/locale/bitcoin_es_DO.ts \
+ qt/locale/bitcoin_es_MX.ts \
+ qt/locale/bitcoin_es.ts \
+ qt/locale/bitcoin_es_UY.ts \
+ qt/locale/bitcoin_et.ts \
+ qt/locale/bitcoin_eu_ES.ts \
+ qt/locale/bitcoin_fa_IR.ts \
+ qt/locale/bitcoin_fa.ts \
+ qt/locale/bitcoin_fi.ts \
+ qt/locale/bitcoin_fr_CA.ts \
+ qt/locale/bitcoin_fr.ts \
+ qt/locale/bitcoin_gl.ts \
+ qt/locale/bitcoin_gu_IN.ts \
+ qt/locale/bitcoin_he.ts \
+ qt/locale/bitcoin_hi_IN.ts \
+ qt/locale/bitcoin_hr.ts \
+ qt/locale/bitcoin_hu.ts \
+ qt/locale/bitcoin_id_ID.ts \
+ qt/locale/bitcoin_it.ts \
+ qt/locale/bitcoin_ja.ts \
+ qt/locale/bitcoin_ka.ts \
+ qt/locale/bitcoin_kk_KZ.ts \
+ qt/locale/bitcoin_ko_KR.ts \
+ qt/locale/bitcoin_ky.ts \
+ qt/locale/bitcoin_la.ts \
+ qt/locale/bitcoin_lt.ts \
+ qt/locale/bitcoin_lv_LV.ts \
+ qt/locale/bitcoin_mn.ts \
+ qt/locale/bitcoin_ms_MY.ts \
+ qt/locale/bitcoin_nb.ts \
+ qt/locale/bitcoin_nl.ts \
+ qt/locale/bitcoin_pam.ts \
+ qt/locale/bitcoin_pl.ts \
+ qt/locale/bitcoin_pt_BR.ts \
+ qt/locale/bitcoin_pt_PT.ts \
+ qt/locale/bitcoin_ro_RO.ts \
+ qt/locale/bitcoin_ru.ts \
+ qt/locale/bitcoin_sah.ts \
+ qt/locale/bitcoin_sk.ts \
+ qt/locale/bitcoin_sl_SI.ts \
+ qt/locale/bitcoin_sq.ts \
+ qt/locale/bitcoin_sr.ts \
+ qt/locale/bitcoin_sv.ts \
+ qt/locale/bitcoin_th_TH.ts \
+ qt/locale/bitcoin_tr.ts \
+ qt/locale/bitcoin_uk.ts \
+ qt/locale/bitcoin_ur_PK.ts \
+ qt/locale/bitcoin_uz@Cyrl.ts \
+ qt/locale/bitcoin_vi.ts \
+ qt/locale/bitcoin_vi_VN.ts \
+ qt/locale/bitcoin_zh_CN.ts \
+ qt/locale/bitcoin_zh_HK.ts \
+ qt/locale/bitcoin_zh_TW.ts
+
+QT_FORMS_UI = \
+ qt/forms/aboutdialog.ui \
+ qt/forms/addressbookpage.ui \
+ qt/forms/askpassphrasedialog.ui \
+ qt/forms/coincontroldialog.ui \
+ qt/forms/editaddressdialog.ui \
+ qt/forms/helpmessagedialog.ui \
+ qt/forms/intro.ui \
+ qt/forms/openuridialog.ui \
+ qt/forms/optionsdialog.ui \
+ qt/forms/overviewpage.ui \
+ qt/forms/receivecoinsdialog.ui \
+ qt/forms/receiverequestdialog.ui \
+ qt/forms/rpcconsole.ui \
+ qt/forms/sendcoinsdialog.ui \
+ qt/forms/sendcoinsentry.ui \
+ qt/forms/signverifymessagedialog.ui \
+ qt/forms/transactiondescdialog.ui
+
+QT_MOC_CPP = \
+ qt/moc_addressbookpage.cpp \
+ qt/moc_addresstablemodel.cpp \
+ qt/moc_askpassphrasedialog.cpp \
+ qt/moc_bitcoinaddressvalidator.cpp \
+ qt/moc_bitcoinamountfield.cpp \
+ qt/moc_bitcoingui.cpp \
+ qt/moc_bitcoinunits.cpp \
+ qt/moc_clientmodel.cpp \
+ qt/moc_coincontroldialog.cpp \
+ qt/moc_coincontroltreewidget.cpp \
+ qt/moc_csvmodelwriter.cpp \
+ qt/moc_editaddressdialog.cpp \
+ qt/moc_guiutil.cpp \
+ qt/moc_intro.cpp \
+ qt/moc_macdockiconhandler.cpp \
+ qt/moc_macnotificationhandler.cpp \
+ qt/moc_monitoreddatamapper.cpp \
+ qt/moc_notificator.cpp \
+ qt/moc_openuridialog.cpp \
+ qt/moc_optionsdialog.cpp \
+ qt/moc_optionsmodel.cpp \
+ qt/moc_overviewpage.cpp \
+ qt/moc_peertablemodel.cpp \
+ qt/moc_paymentserver.cpp \
+ qt/moc_qvalidatedlineedit.cpp \
+ qt/moc_qvaluecombobox.cpp \
+ qt/moc_receivecoinsdialog.cpp \
+ qt/moc_receiverequestdialog.cpp \
+ qt/moc_recentrequeststablemodel.cpp \
+ qt/moc_rpcconsole.cpp \
+ qt/moc_sendcoinsdialog.cpp \
+ qt/moc_sendcoinsentry.cpp \
+ qt/moc_signverifymessagedialog.cpp \
+ qt/moc_splashscreen.cpp \
+ qt/moc_trafficgraphwidget.cpp \
+ qt/moc_transactiondesc.cpp \
+ qt/moc_transactiondescdialog.cpp \
+ qt/moc_transactionfilterproxy.cpp \
+ qt/moc_transactiontablemodel.cpp \
+ qt/moc_transactionview.cpp \
+ qt/moc_utilitydialog.cpp \
+ qt/moc_walletframe.cpp \
+ qt/moc_walletmodel.cpp \
+ qt/moc_walletview.cpp
+
+BITCOIN_MM = \
+ qt/macdockiconhandler.mm \
+ qt/macnotificationhandler.mm
+
+QT_MOC = \
+ qt/bitcoin.moc \
+ qt/intro.moc \
+ qt/overviewpage.moc \
+ qt/rpcconsole.moc
+
+QT_QRC_CPP = qt/qrc_bitcoin.cpp
+QT_QRC = qt/bitcoin.qrc
+
+PROTOBUF_CC = qt/paymentrequest.pb.cc
+PROTOBUF_H = qt/paymentrequest.pb.h
+PROTOBUF_PROTO = qt/paymentrequest.proto
+
+BITCOIN_QT_H = \
+ qt/addressbookpage.h \
+ qt/addresstablemodel.h \
+ qt/askpassphrasedialog.h \
+ qt/bitcoinaddressvalidator.h \
+ qt/bitcoinamountfield.h \
+ qt/bitcoingui.h \
+ qt/bitcoinunits.h \
+ qt/clientmodel.h \
+ qt/coincontroldialog.h \
+ qt/coincontroltreewidget.h \
+ qt/csvmodelwriter.h \
+ qt/editaddressdialog.h \
+ qt/guiconstants.h \
+ qt/guiutil.h \
+ qt/intro.h \
+ qt/macdockiconhandler.h \
+ qt/macnotificationhandler.h \
+ qt/monitoreddatamapper.h \
+ qt/notificator.h \
+ qt/openuridialog.h \
+ qt/optionsdialog.h \
+ qt/optionsmodel.h \
+ qt/overviewpage.h \
+ qt/paymentrequestplus.h \
+ qt/paymentserver.h \
+ qt/peertablemodel.h \
+ qt/qvalidatedlineedit.h \
+ qt/qvaluecombobox.h \
+ qt/receivecoinsdialog.h \
+ qt/receiverequestdialog.h \
+ qt/recentrequeststablemodel.h \
+ qt/rpcconsole.h \
+ qt/sendcoinsdialog.h \
+ qt/sendcoinsentry.h \
+ qt/signverifymessagedialog.h \
+ qt/splashscreen.h \
+ qt/trafficgraphwidget.h \
+ qt/transactiondesc.h \
+ qt/transactiondescdialog.h \
+ qt/transactionfilterproxy.h \
+ qt/transactionrecord.h \
+ qt/transactiontablemodel.h \
+ qt/transactionview.h \
+ qt/utilitydialog.h \
+ qt/walletframe.h \
+ qt/walletmodel.h \
+ qt/walletmodeltransaction.h \
+ qt/walletview.h \
+ qt/winshutdownmonitor.h
+
+RES_ICONS = \
+ qt/res/icons/add.png \
+ qt/res/icons/address-book.png \
+ qt/res/icons/bitcoin.ico \
+ qt/res/icons/bitcoin.png \
+ qt/res/icons/bitcoin_testnet.ico \
+ qt/res/icons/bitcoin_testnet.png \
+ qt/res/icons/clock1.png \
+ qt/res/icons/clock2.png \
+ qt/res/icons/clock3.png \
+ qt/res/icons/clock4.png \
+ qt/res/icons/clock5.png \
+ qt/res/icons/configure.png \
+ qt/res/icons/connect0_16.png \
+ qt/res/icons/connect1_16.png \
+ qt/res/icons/connect2_16.png \
+ qt/res/icons/connect3_16.png \
+ qt/res/icons/connect4_16.png \
+ qt/res/icons/debugwindow.png \
+ qt/res/icons/edit.png \
+ qt/res/icons/editcopy.png \
+ qt/res/icons/editpaste.png \
+ qt/res/icons/export.png \
+ qt/res/icons/filesave.png \
+ qt/res/icons/history.png \
+ qt/res/icons/key.png \
+ qt/res/icons/lock_closed.png \
+ qt/res/icons/lock_open.png \
+ qt/res/icons/overview.png \
+ qt/res/icons/qrcode.png \
+ qt/res/icons/quit.png \
+ qt/res/icons/receive.png \
+ qt/res/icons/remove.png \
+ qt/res/icons/send.png \
+ qt/res/icons/synced.png \
+ qt/res/icons/toolbar.png \
+ qt/res/icons/toolbar_testnet.png \
+ qt/res/icons/transaction0.png \
+ qt/res/icons/transaction2.png \
+ qt/res/icons/transaction_conflicted.png \
+ qt/res/icons/tx_inout.png \
+ qt/res/icons/tx_input.png \
+ qt/res/icons/tx_output.png \
+ qt/res/icons/tx_mined.png
+
+BITCOIN_QT_CPP = \
+ qt/bitcoinaddressvalidator.cpp \
+ qt/bitcoinamountfield.cpp \
+ qt/bitcoingui.cpp \
+ qt/bitcoinunits.cpp \
+ qt/clientmodel.cpp \
+ qt/csvmodelwriter.cpp \
+ qt/guiutil.cpp \
+ qt/intro.cpp \
+ qt/monitoreddatamapper.cpp \
+ qt/notificator.cpp \
+ qt/optionsdialog.cpp \
+ qt/optionsmodel.cpp \
+ qt/peertablemodel.cpp \
+ qt/qvalidatedlineedit.cpp \
+ qt/qvaluecombobox.cpp \
+ qt/rpcconsole.cpp \
+ qt/splashscreen.cpp \
+ qt/trafficgraphwidget.cpp \
+ qt/utilitydialog.cpp \
+ qt/winshutdownmonitor.cpp
+
+if ENABLE_WALLET
+BITCOIN_QT_CPP += \
+ qt/addressbookpage.cpp \
+ qt/addresstablemodel.cpp \
+ qt/askpassphrasedialog.cpp \
+ qt/coincontroldialog.cpp \
+ qt/coincontroltreewidget.cpp \
+ qt/editaddressdialog.cpp \
+ qt/openuridialog.cpp \
+ qt/overviewpage.cpp \
+ qt/paymentrequestplus.cpp \
+ qt/paymentserver.cpp \
+ qt/receivecoinsdialog.cpp \
+ qt/receiverequestdialog.cpp \
+ qt/recentrequeststablemodel.cpp \
+ qt/sendcoinsdialog.cpp \
+ qt/sendcoinsentry.cpp \
+ qt/signverifymessagedialog.cpp \
+ qt/transactiondesc.cpp \
+ qt/transactiondescdialog.cpp \
+ qt/transactionfilterproxy.cpp \
+ qt/transactionrecord.cpp \
+ qt/transactiontablemodel.cpp \
+ qt/transactionview.cpp \
+ qt/walletframe.cpp \
+ qt/walletmodel.cpp \
+ qt/walletmodeltransaction.cpp \
+ qt/walletview.cpp
+endif
+
+RES_IMAGES = \
+ qt/res/images/about.png \
+ qt/res/images/splash.png \
+ qt/res/images/splash_testnet.png
+
+RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png)
+
+BITCOIN_RC = qt/res/bitcoin-qt-res.rc
+
+BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \
+ -I$(builddir)/qt/forms
+
+qt_libbitcoinqt_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
+ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
+
+qt_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_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
+ $(PROTOBUF_H) $(QT_QRC_CPP)
+
+# forms/foo.h -> forms/ui_foo.h
+QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h))))
+
+# Most files will depend on the forms and moc files as includes. Generate them
+# before anything else.
+$(QT_MOC): $(QT_FORMS_H)
+$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC)
+
+#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)
+
+# bitcoin-qt binary #
+qt_bitcoin_qt_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
+ $(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
+
+qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp
+if TARGET_DARWIN
+ qt_bitcoin_qt_SOURCES += $(BITCOIN_MM)
+endif
+if TARGET_WINDOWS
+ qt_bitcoin_qt_SOURCES += $(BITCOIN_RC)
+endif
+qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER)
+if ENABLE_WALLET
+qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
+endif
+qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
+ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
+qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
+
+#locale/foo.ts -> locale/foo.qm
+QT_QM=$(QT_TS:.ts=.qm)
+
+.SECONDARY: $(QT_QM)
+
+qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES)
+ @test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
+ $(AM_V_GEN) cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py
+
+translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
+ @test -n $(LUPDATE) || echo "lupdate is required for updating translations"
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts qt/locale/bitcoin_en.ts
+
+$(QT_QRC_CPP): $(QT_QRC) $(QT_QM) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H)
+ @test -f $(RCC)
+ $(AM_V_GEN) cd $(srcdir); QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \
+ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $(abs_builddir)/$@
+
+CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno
+
+CLEANFILES += $(CLEAN_QT)
+
+bitcoin_qt_clean: FORCE
+ rm -f $(CLEAN_QT) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) qt/bitcoin-qt$(EXEEXT) $(LIBBITCOINQT)
+
+bitcoin_qt : qt/bitcoin-qt$(EXEEXT)
+
+ui_%.h: %.ui
+ @test -f $(UIC)
+ @$(MKDIR_P) $(@D)
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false)
+
+%.moc: %.cpp
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \
+ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
+
+moc_%.cpp: %.h
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \
+ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
+
+%.qm: %.ts
+ @test -f $(LRELEASE)
+ @$(MKDIR_P) $(@D)
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LRELEASE) -silent $< -qm $@
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
new file mode 100644
index 0000000000..e0b49d0240
--- /dev/null
+++ b/src/Makefile.qttest.include
@@ -0,0 +1,48 @@
+bin_PROGRAMS += qt/test/test_bitcoin-qt
+TESTS += qt/test/test_bitcoin-qt
+
+TEST_QT_MOC_CPP = qt/test/moc_uritests.cpp
+
+if ENABLE_WALLET
+TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp
+endif
+
+TEST_QT_H = \
+ qt/test/uritests.h \
+ qt/test/paymentrequestdata.h \
+ qt/test/paymentservertests.h
+
+qt_test_test_bitcoin_qt_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
+ $(QT_INCLUDES) $(QT_TEST_INCLUDES)
+
+qt_test_test_bitcoin_qt_SOURCES = \
+ qt/test/test_main.cpp \
+ qt/test/uritests.cpp \
+ $(TEST_QT_H)
+if ENABLE_WALLET
+qt_test_test_bitcoin_qt_SOURCES += \
+ qt/test/paymentservertests.cpp
+endif
+
+nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
+
+qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER)
+if ENABLE_WALLET
+qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
+endif
+qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
+ $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
+ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
+qt_test_test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
+
+CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno
+
+CLEANFILES += $(CLEAN_BITCOIN_QT_TEST)
+
+test_bitcoin_qt : qt/test/test_bitcoin-qt$(EXEEXT)
+
+test_bitcoin_qt_check : qt/test/test_bitcoin-qt$(EXEEXT) FORCE
+ $(MAKE) check-TESTS TESTS=$^
+
+test_bitcoin_qt_clean: FORCE
+ rm -f $(CLEAN_BITCOIN_QT_TEST) $(qt_test_test_bitcoin_qt_OBJECTS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
new file mode 100644
index 0000000000..988830260c
--- /dev/null
+++ b/src/Makefile.test.include
@@ -0,0 +1,101 @@
+TESTS += test/test_bitcoin
+bin_PROGRAMS += test/test_bitcoin
+TEST_SRCDIR = test
+TEST_BINARY=test/test_bitcoin$(EXEEXT)
+
+JSON_TEST_FILES = \
+ test/data/script_valid.json \
+ test/data/base58_keys_valid.json \
+ test/data/sig_canonical.json \
+ test/data/sig_noncanonical.json \
+ test/data/base58_encode_decode.json \
+ test/data/base58_keys_invalid.json \
+ test/data/script_invalid.json \
+ test/data/tx_invalid.json \
+ test/data/tx_valid.json \
+ test/data/sighash.json
+
+RAW_TEST_FILES = test/data/alertTests.raw
+
+GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
+
+BITCOIN_TESTS =\
+ test/bignum.h \
+ test/alert_tests.cpp \
+ test/allocator_tests.cpp \
+ test/base32_tests.cpp \
+ test/base58_tests.cpp \
+ test/base64_tests.cpp \
+ test/bloom_tests.cpp \
+ test/canonical_tests.cpp \
+ test/checkblock_tests.cpp \
+ test/Checkpoints_tests.cpp \
+ test/compress_tests.cpp \
+ test/DoS_tests.cpp \
+ test/getarg_tests.cpp \
+ test/key_tests.cpp \
+ test/main_tests.cpp \
+ test/miner_tests.cpp \
+ test/mruset_tests.cpp \
+ test/multisig_tests.cpp \
+ test/netbase_tests.cpp \
+ test/pmt_tests.cpp \
+ test/rpc_tests.cpp \
+ test/script_P2SH_tests.cpp \
+ test/script_tests.cpp \
+ test/serialize_tests.cpp \
+ test/sigopcount_tests.cpp \
+ test/test_bitcoin.cpp \
+ test/transaction_tests.cpp \
+ test/uint256_tests.cpp \
+ test/util_tests.cpp \
+ test/scriptnum_tests.cpp \
+ test/sighash_tests.cpp
+
+if ENABLE_WALLET
+BITCOIN_TESTS += \
+ test/accounting_tests.cpp \
+ test/wallet_tests.cpp \
+ test/rpc_wallet_tests.cpp
+endif
+
+test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
+test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS)
+test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
+ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
+if ENABLE_WALLET
+test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
+endif
+test_test_bitcoin_LDADD += $(BDB_LIBS)
+
+nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
+
+$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
+
+CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
+
+CLEANFILES += $(CLEAN_BITCOIN_TEST)
+
+bitcoin_test: $(TEST_BINARY)
+
+bitcoin_test_check: $(TEST_BINARY) FORCE
+ $(MAKE) check-TESTS TESTS=$^
+
+bitcoin_test_clean : FORCE
+ rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
+
+%.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/core.cpp b/src/core.cpp
index aadcb44b98..6039986e6c 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -72,6 +72,25 @@ void CTxOut::print() const
LogPrintf("%s\n", ToString());
}
+CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize)
+{
+ if (nSize > 0)
+ nSatoshisPerK = nFeePaid*1000/nSize;
+ else
+ nSatoshisPerK = 0;
+}
+
+int64_t CFeeRate::GetFee(size_t nSize)
+{
+ return nSatoshisPerK*nSize / 1000;
+}
+
+std::string CFeeRate::ToString() const
+{
+ std::string result = FormatMoney(nSatoshisPerK) + " BTC/kB";
+ return result;
+}
+
uint256 CTransaction::GetHash() const
{
return SerializeHash(*this);
diff --git a/src/core.h b/src/core.h
index ba7f691119..0e59129349 100644
--- a/src/core.h
+++ b/src/core.h
@@ -112,6 +112,31 @@ public:
+/** Type-safe wrapper class to for fee rates
+ * (how much to pay based on transaction size)
+ */
+class CFeeRate
+{
+private:
+ int64_t nSatoshisPerK; // unit is satoshis-per-1,000-bytes
+public:
+ CFeeRate() : nSatoshisPerK(0) { }
+ explicit CFeeRate(int64_t _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
+ CFeeRate(int64_t nFeePaid, size_t nSize);
+ CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
+
+ int64_t GetFee(size_t size); // unit returned is satoshis
+ int64_t GetFeePerK() { return GetFee(1000); } // satoshis-per-1000-bytes
+
+ friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
+ friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
+ friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
+
+ std::string ToString() const;
+
+ IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); )
+};
+
/** An output of a transaction. It contains the public key that the next input
* must be able to sign with to claim it.
@@ -148,17 +173,18 @@ public:
uint256 GetHash() const;
- bool IsDust(int64_t nMinRelayTxFee) const
+ bool IsDust(CFeeRate minRelayTxFee) const
{
- // "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
+ // "Dust" is defined in terms of CTransaction::minRelayTxFee,
// which has units satoshis-per-kilobyte.
// If you'd pay more than 1/3 in fees
// to spend something, then we consider it dust.
// A typical txout is 34 bytes big, and will
- // need a CTxIn of at least 148 bytes to spend,
+ // need a CTxIn of at least 148 bytes to spend:
// so dust is a txout less than 546 satoshis
- // with default nMinRelayTxFee.
- return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee);
+ // with default minRelayTxFee.
+ size_t nSize = GetSerializeSize(SER_DISK,0)+148u;
+ return (nValue < 3*minRelayTxFee.GetFee(nSize));
}
friend bool operator==(const CTxOut& a, const CTxOut& b)
@@ -183,8 +209,8 @@ public:
class CTransaction
{
public:
- static int64_t nMinTxFee;
- static int64_t nMinRelayTxFee;
+ static CFeeRate minTxFee;
+ static CFeeRate minRelayTxFee;
static const int CURRENT_VERSION=1;
int nVersion;
std::vector<CTxIn> vin;
diff --git a/src/init.cpp b/src/init.cpp
index a225c3f964..ca348b614e 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -40,7 +40,6 @@ using namespace std;
using namespace boost;
#ifdef ENABLE_WALLET
-std::string strWalletFile;
CWallet* pwalletMain;
#endif
@@ -60,6 +59,7 @@ enum BindFlags {
BF_REPORT_ERROR = (1U << 1)
};
+static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
//////////////////////////////////////////////////////////////////////////////
//
@@ -122,6 +122,14 @@ void Shutdown()
#endif
StopNode();
UnregisterNodeSignals(GetNodeSignals());
+
+ boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_fileout = CAutoFile(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
+ if (est_fileout)
+ mempool.WriteFeeEstimates(est_fileout);
+ else
+ LogPrintf("failed to write fee estimates");
+
{
LOCK(cs_main);
#ifdef ENABLE_WALLET
@@ -206,6 +214,7 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n";
strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n";
strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n";
+ strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n";
strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n";
strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n";
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n";
@@ -281,8 +290,8 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n";
strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n";
}
- strUsage += " -mintxfee=<amt> " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::nMinTxFee) + ")" + "\n";
- strUsage += " -minrelaytxfee=<amt> " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::nMinRelayTxFee) + ")" + "\n";
+ strUsage += " -mintxfee=<amt> " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::minTxFee.GetFeePerK()) + ")" + "\n";
+ strUsage += " -minrelaytxfee=<amt> " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::minRelayTxFee.GetFeePerK()) + ")" + "\n";
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
if (GetBoolArg("-help-debug", false))
{
@@ -561,7 +570,7 @@ bool AppInit2(boost::thread_group& threadGroup)
{
int64_t n = 0;
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
- CTransaction::nMinTxFee = n;
+ CTransaction::minTxFee = CFeeRate(n);
else
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
}
@@ -569,7 +578,7 @@ bool AppInit2(boost::thread_group& threadGroup)
{
int64_t n = 0;
if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0)
- CTransaction::nMinRelayTxFee = n;
+ CTransaction::minRelayTxFee = CFeeRate(n);
else
return InitError(strprintf(_("Invalid amount for -minrelaytxfee=<amount>: '%s'"), mapArgs["-minrelaytxfee"]));
}
@@ -577,14 +586,16 @@ bool AppInit2(boost::thread_group& threadGroup)
#ifdef ENABLE_WALLET
if (mapArgs.count("-paytxfee"))
{
- if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
+ int64_t nFeePerK = 0;
+ if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"]));
- if (nTransactionFee > nHighTransactionFeeWarning)
+ if (nFeePerK > nHighTransactionFeeWarning)
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
+ payTxFee = CFeeRate(nFeePerK, 1000);
}
bSpendZeroConfChange = GetArg("-spendzeroconfchange", true);
- strWalletFile = GetArg("-wallet", "wallet.dat");
+ std::string strWalletFile = GetArg("-wallet", "wallet.dat");
#endif
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
@@ -614,6 +625,7 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", strDataDir);
+ LogPrintf("Using config file %s\n", GetConfigFile().string());
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
std::ostringstream strErrors;
@@ -733,12 +745,12 @@ bool AppInit2(boost::thread_group& threadGroup)
}
// see Step 2: parameter interactions for more information about these
- fNoListen = !GetBoolArg("-listen", true);
+ fListen = GetBoolArg("-listen", true);
fDiscover = GetBoolArg("-discover", true);
fNameLookup = GetBoolArg("-dns", true);
bool fBound = false;
- if (!fNoListen) {
+ if (fListen) {
if (mapArgs.count("-bind")) {
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
CService addrBind;
@@ -931,6 +943,11 @@ bool AppInit2(boost::thread_group& threadGroup)
return false;
}
+ boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_filein = CAutoFile(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION);
+ if (est_filein)
+ mempool.ReadFeeEstimates(est_filein);
+
// ********************************************************* Step 8: load wallet
#ifdef ENABLE_WALLET
if (fDisableWallet) {
diff --git a/src/init.h b/src/init.h
index 2f56923055..4a967bea37 100644
--- a/src/init.h
+++ b/src/init.h
@@ -14,7 +14,6 @@ namespace boost {
class thread_group;
};
-extern std::string strWalletFile;
extern CWallet* pwalletMain;
void StartShutdown();
diff --git a/src/m4/bitcoin_qt.m4 b/src/m4/bitcoin_qt.m4
index e71ecd7172..244b03a5c2 100644
--- a/src/m4/bitcoin_qt.m4
+++ b/src/m4/bitcoin_qt.m4
@@ -100,7 +100,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
BITCOIN_QT_PATH_PROGS([LRELEASE], [lrelease-qt${bitcoin_qt_got_major_vers} lrelease${bitcoin_qt_got_major_vers} lrelease], $qt_bin_path)
BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt${bitcoin_qt_got_major_vers} lupdate${bitcoin_qt_got_major_vers} lupdate],$qt_bin_path, yes)
- MOC_DEFS='-DHAVE_CONFIG_H -I$(top_srcdir)/src'
+ MOC_DEFS='-DHAVE_CONFIG_H -I$(srcdir)'
case $host in
*darwin*)
BITCOIN_QT_CHECK([
diff --git a/src/main.cpp b/src/main.cpp
index 2f24beecc6..5d1ff94f5d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -40,7 +40,6 @@ CTxMemPool mempool;
map<uint256, CBlockIndex*> mapBlockIndex;
CChain chainActive;
-CChain chainMostWork;
int64_t nTimeBestReceived = 0;
int nScriptCheckThreads = 0;
bool fImporting = false;
@@ -50,9 +49,9 @@ bool fTxIndex = false;
unsigned int nCoinCacheSize = 5000;
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
-int64_t CTransaction::nMinTxFee = 10000; // Override with -mintxfee
+CFeeRate CTransaction::minTxFee = CFeeRate(10000); // Override with -mintxfee
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
-int64_t CTransaction::nMinRelayTxFee = 1000;
+CFeeRate CTransaction::minRelayTxFee = CFeeRate(1000);
struct COrphanBlock {
uint256 hashBlock;
@@ -398,6 +397,12 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
return Genesis();
}
+CBlockIndex *CChain::FindFork(CBlockIndex *pindex) const {
+ while (pindex && !Contains(pindex))
+ pindex = pindex->pprev;
+ return pindex;
+}
+
CCoinsViewCache *pcoinsTip = NULL;
CBlockTreeDB *pblocktree = NULL;
@@ -543,7 +548,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
}
if (whichType == TX_NULL_DATA)
nDataOut++;
- else if (txout.IsDust(CTransaction::nMinRelayTxFee)) {
+ else if (txout.IsDust(CTransaction::minRelayTxFee)) {
reason = "dust";
return false;
}
@@ -783,10 +788,10 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode)
{
- // Base fee is either nMinTxFee or nMinRelayTxFee
- int64_t nBaseFee = (mode == GMF_RELAY) ? tx.nMinRelayTxFee : tx.nMinTxFee;
+ // Base fee is either minTxFee or minRelayTxFee
+ CFeeRate baseFeeRate = (mode == GMF_RELAY) ? tx.minRelayTxFee : tx.minTxFee;
- int64_t nMinFee = (1 + (int64_t)nBytes / 1000) * nBaseFee;
+ int64_t nMinFee = baseFeeRate.GetFee(nBytes);
if (fAllowFree)
{
@@ -800,16 +805,6 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree,
nMinFee = 0;
}
- // This code can be removed after enough miners have upgraded to version 0.9.
- // Until then, be safe when sending and require a fee if any output
- // is less than CENT:
- if (nMinFee < nBaseFee && mode == GMF_SEND)
- {
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
- if (txout.nValue < CENT)
- nMinFee = nBaseFee;
- }
-
if (!MoneyRange(nMinFee))
nMinFee = MAX_MONEY;
return nMinFee;
@@ -861,6 +856,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
CCoinsView dummy;
CCoinsViewCache view(dummy);
+ int64_t nValueIn = 0;
{
LOCK(pool.cs);
CCoinsViewMemPool viewMemPool(*pcoinsTip, pool);
@@ -889,6 +885,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Bring the best block into scope
view.GetBestBlock();
+ nValueIn = view.GetValueIn(tx);
+
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
view.SetBackend(dummy);
}
@@ -901,7 +899,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// you should add code here to check that the transaction does a
// reasonable number of ECDSA signature verifications.
- int64_t nValueIn = view.GetValueIn(tx);
int64_t nValueOut = tx.GetValueOut();
int64_t nFees = nValueIn-nValueOut;
double dPriority = view.GetPriority(tx, chainActive.Height());
@@ -916,10 +913,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
hash.ToString(), nFees, txMinFee),
REJECT_INSUFFICIENTFEE, "insufficient fee");
- // Continuously rate-limit free transactions
+ // Continuously rate-limit free (really, very-low-fee)transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
- if (fLimitFree && nFees < CTransaction::nMinRelayTxFee)
+ if (fLimitFree && nFees < CTransaction::minRelayTxFee.GetFee(nSize))
{
static CCriticalSection csFreeLimiter;
static double dFreeCount;
@@ -940,10 +937,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
dFreeCount += nSize;
}
- if (fRejectInsaneFee && nFees > CTransaction::nMinRelayTxFee * 10000)
+ if (fRejectInsaneFee && nFees > CTransaction::minRelayTxFee.GetFee(nSize) * 10000)
return error("AcceptToMemoryPool: : insane fees %s, %d > %d",
hash.ToString(),
- nFees, CTransaction::nMinRelayTxFee * 10000);
+ nFees, CTransaction::minRelayTxFee.GetFee(nSize) * 10000);
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
@@ -1160,7 +1157,7 @@ uint256 static GetOrphanRoot(const uint256& hash)
// Remove a random orphan block (which does not have any dependent orphans).
void static PruneOrphanBlocks()
{
- if (mapOrphanBlocksByPrev.size() <= MAX_ORPHAN_BLOCKS)
+ if (mapOrphanBlocksByPrev.size() <= (size_t)std::max((int64_t)0, GetArg("-maxorphanblocks", DEFAULT_MAX_ORPHAN_BLOCKS)))
return;
// Pick a random orphan block.
@@ -1898,6 +1895,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
for (unsigned int i = 0; i < block.vtx.size(); i++)
g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block);
+ // Watch for changes to the previous coinbase transaction.
+ static uint256 hashPrevBestCoinBase;
+ g_signals.UpdatedTransaction(hashPrevBestCoinBase);
+ hashPrevBestCoinBase = block.GetTxHash(0);
+
return true;
}
@@ -2027,11 +2029,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
return false;
// Remove conflicting transactions from the mempool.
list<CTransaction> txConflicted;
- BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- list<CTransaction> unused;
- mempool.remove(tx, unused);
- mempool.removeConflicts(tx, txConflicted);
- }
+ mempool.removeForBlock(block.vtx, pindexNew->nHeight, txConflicted);
mempool.check(pcoinsTip);
// Update chainActive & related variables.
UpdateTip(pindexNew);
@@ -2047,23 +2045,17 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
return true;
}
-// Make chainMostWork correspond to the chain with the most work in it, that isn't
+// Return the tip of the chain with the most work in it, that isn't
// known to be invalid (it's however far from certain to be valid).
-void static FindMostWorkChain() {
- CBlockIndex *pindexNew = NULL;
-
- // In case the current best is invalid, do not consider it.
- while (chainMostWork.Tip() && (chainMostWork.Tip()->nStatus & BLOCK_FAILED_MASK)) {
- setBlockIndexValid.erase(chainMostWork.Tip());
- chainMostWork.SetTip(chainMostWork.Tip()->pprev);
- }
-
+static CBlockIndex* FindMostWorkChain() {
do {
+ CBlockIndex *pindexNew = NULL;
+
// Find the best candidate header.
{
std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexValid.rbegin();
if (it == setBlockIndexValid.rend())
- return;
+ return NULL;
pindexNew = *it;
}
@@ -2087,70 +2079,111 @@ void static FindMostWorkChain() {
}
pindexTest = pindexTest->pprev;
}
- if (fInvalidAncestor)
- continue;
-
- break;
+ if (!fInvalidAncestor)
+ return pindexNew;
} while(true);
-
- // Check whether it's actually an improvement.
- if (chainMostWork.Tip() && !CBlockIndexWorkComparator()(chainMostWork.Tip(), pindexNew))
- return;
-
- // We have a new best.
- chainMostWork.SetTip(pindexNew);
}
-// Try to activate to the most-work chain (thereby connecting it).
-bool ActivateBestChain(CValidationState &state) {
- LOCK(cs_main);
+// Try to make some progress towards making pindexMostWork the active block.
+static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) {
+ AssertLockHeld(cs_main);
+ bool fInvalidFound = false;
CBlockIndex *pindexOldTip = chainActive.Tip();
- bool fComplete = false;
- while (!fComplete) {
- FindMostWorkChain();
- fComplete = true;
+ CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
- // Check whether we have something to do.
- if (chainMostWork.Tip() == NULL) break;
+ // Disconnect active blocks which are no longer in the best chain.
+ while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
+ if (!DisconnectTip(state))
+ return false;
+ }
- // Disconnect active blocks which are no longer in the best chain.
- while (chainActive.Tip() && !chainMostWork.Contains(chainActive.Tip())) {
- if (!DisconnectTip(state))
- return false;
- }
+ // Build list of new blocks to connect.
+ std::vector<CBlockIndex*> vpindexToConnect;
+ vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1));
+ while (pindexMostWork && pindexMostWork != pindexFork) {
+ vpindexToConnect.push_back(pindexMostWork);
+ pindexMostWork = pindexMostWork->pprev;
+ }
- // Connect new blocks.
- while (!chainActive.Contains(chainMostWork.Tip())) {
- CBlockIndex *pindexConnect = chainMostWork[chainActive.Height() + 1];
- if (!ConnectTip(state, pindexConnect)) {
- if (state.IsInvalid()) {
- // The block violates a consensus rule.
- if (!state.CorruptionPossible())
- InvalidChainFound(chainMostWork.Tip());
- fComplete = false;
- state = CValidationState();
- break;
- } else {
- // A system error occurred (disk space, database error, ...).
- return false;
- }
+ // Connect new blocks.
+ BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
+ if (!ConnectTip(state, pindexConnect)) {
+ if (state.IsInvalid()) {
+ // The block violates a consensus rule.
+ if (!state.CorruptionPossible())
+ InvalidChainFound(vpindexToConnect.back());
+ state = CValidationState();
+ fInvalidFound = true;
+ break;
+ } else {
+ // A system error occurred (disk space, database error, ...).
+ return false;
+ }
+ } else {
+ if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
+ // We're in a better position than we were. Return temporarily to release the lock.
+ break;
}
}
}
- if (chainActive.Tip() != pindexOldTip) {
- std::string strCmd = GetArg("-blocknotify", "");
- if (!IsInitialBlockDownload() && !strCmd.empty())
+ // Callbacks/notifications for a new best chain.
+ if (fInvalidFound)
+ CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
+ else
+ CheckForkWarningConditions();
+
+ if (!pblocktree->Flush())
+ return state.Abort(_("Failed to sync block index"));
+
+ return true;
+}
+
+bool ActivateBestChain(CValidationState &state) {
+ CBlockIndex *pindexNewTip = NULL;
+ CBlockIndex *pindexMostWork = NULL;
+ do {
+ boost::this_thread::interruption_point();
+
+ bool fInitialDownload;
{
- boost::replace_all(strCmd, "%s", chainActive.Tip()->GetBlockHash().GetHex());
- boost::thread t(runCommand, strCmd); // thread runs free
+ LOCK(cs_main);
+ pindexMostWork = FindMostWorkChain();
+
+ // Whether we have anything to do at all.
+ if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip())
+ return true;
+
+ if (!ActivateBestChainStep(state, pindexMostWork))
+ return false;
+
+ pindexNewTip = chainActive.Tip();
+ fInitialDownload = IsInitialBlockDownload();
}
- }
+ // When we reach this point, we switched to a new tip (stored in pindexNewTip).
+
+ // Notifications/callbacks that can run without cs_main
+ if (!fInitialDownload) {
+ uint256 hashNewTip = pindexNewTip->GetBlockHash();
+ // Relay inventory, but don't relay old inventory during initial block download.
+ int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
+ pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
+
+ std::string strCmd = GetArg("-blocknotify", "");
+ if (!strCmd.empty()) {
+ boost::replace_all(strCmd, "%s", hashNewTip.GetHex());
+ boost::thread t(runCommand, strCmd); // thread runs free
+ }
+ }
+ uiInterface.NotifyBlocksChanged();
+ } while(pindexMostWork != chainActive.Tip());
return true;
}
-
CBlockIndex* AddToBlockIndex(CBlockHeader& block)
{
// Check for duplicate
@@ -2210,26 +2243,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
return state.Abort(_("Failed to write block index"));
- // New best?
- if (!ActivateBestChain(state))
- return false;
-
- LOCK(cs_main);
- if (pindexNew == chainActive.Tip())
- {
- // Clear fork warning if its no longer applicable
- CheckForkWarningConditions();
- // Notify UI to display prev block's coinbase if it was ours
- static uint256 hashPrevBestCoinBase;
- g_signals.UpdatedTransaction(hashPrevBestCoinBase);
- hashPrevBestCoinBase = block.GetTxHash(0);
- } else
- CheckForkWarningConditionsOnNewFork(pindexNew);
-
- if (!pblocktree->Flush())
- return state.Abort(_("Failed to sync block index"));
-
- uiInterface.NotifyBlocksChanged();
return true;
}
@@ -2503,7 +2516,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
}
int nHeight = pindex->nHeight;
- uint256 hash = pindex->GetBlockHash();
// Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@@ -2543,16 +2555,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
return state.Abort(_("System error: ") + e.what());
}
- // Relay inventory, but don't relay old inventory during initial block download
- int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
- if (chainActive.Tip()->GetBlockHash() == hash)
- {
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
- pnode->PushInventory(CInv(MSG_BLOCK, hash));
- }
-
return true;
}
@@ -2583,10 +2585,11 @@ void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
{
- AssertLockHeld(cs_main);
-
// Check for duplicate
uint256 hash = pblock->GetHash();
+
+ {
+ LOCK(cs_main);
if (mapBlockIndex.count(hash))
return state.Invalid(error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString()), 0, "duplicate");
if (mapOrphanBlocks.count(hash))
@@ -2655,7 +2658,11 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapOrphanBlocksByPrev.erase(hashPrev);
}
- LogPrintf("ProcessBlock: ACCEPTED\n");
+ }
+
+ if (!ActivateBestChain(state))
+ return error("ProcessBlock() : ActivateBestChain failed");
+
return true;
}
@@ -3091,6 +3098,8 @@ bool InitBlockIndex() {
CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("LoadBlockIndex() : genesis block not accepted");
+ if (!ActivateBestChain(state))
+ return error("LoadBlockIndex() : genesis block cannot be activated");
} catch(std::runtime_error &e) {
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
}
@@ -3220,7 +3229,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
// process block
if (nBlockPos >= nStartByte) {
- LOCK(cs_main);
if (dbp)
dbp->nPos = nBlockPos;
CValidationState state;
@@ -3384,7 +3392,8 @@ void static ProcessGetData(CNode* pfrom)
{
// Send block from disk
CBlock block;
- assert(ReadBlockFromDisk(block, (*mi).second));
+ if (!ReadBlockFromDisk(block, (*mi).second))
+ assert(!"cannot load block from disk");
if (inv.type == MSG_BLOCK)
pfrom->PushMessage("block", block);
else // MSG_FILTERED_BLOCK)
@@ -3556,7 +3565,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!pfrom->fInbound)
{
// Advertise our address
- if (!fNoListen && !IsInitialBlockDownload())
+ if (fListen && !IsInitialBlockDownload())
{
CAddress addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable())
@@ -3908,10 +3917,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CInv inv(MSG_BLOCK, block.GetHash());
pfrom->AddInventoryKnown(inv);
- LOCK(cs_main);
- // Remember who we got this block from.
- mapBlockSource[inv.hash] = pfrom->GetId();
- MarkBlockAsReceived(inv.hash, pfrom->GetId());
+ {
+ LOCK(cs_main);
+ // Remember who we got this block from.
+ mapBlockSource[inv.hash] = pfrom->GetId();
+ MarkBlockAsReceived(inv.hash, pfrom->GetId());
+ }
CValidationState state;
ProcessBlock(state, pfrom, &block);
@@ -4324,7 +4335,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pnode->setAddrKnown.clear();
// Rebroadcast our address
- if (!fNoListen)
+ if (fListen)
{
CAddress addr = GetLocalAddress(&pnode->addr);
if (addr.IsRoutable())
diff --git a/src/main.h b/src/main.h
index 58515b44b9..4ef3800084 100644
--- a/src/main.h
+++ b/src/main.h
@@ -45,8 +45,8 @@ static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** The maximum number of orphan transactions kept in memory */
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
-/** The maximum number of orphan blocks kept in memory */
-static const unsigned int MAX_ORPHAN_BLOCKS = 750;
+/** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */
+static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
@@ -292,13 +292,6 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& mapInputs);
-inline bool AllowFree(double dPriority)
-{
- // Large (in bytes) low-priority (new, small-coin) transactions
- // need a fee.
- return dPriority > COIN * 144 / 250;
-}
-
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
// instead of being performed inline.
@@ -1087,14 +1080,14 @@ public:
/** Find the last common block between this chain and a locator. */
CBlockIndex *FindFork(const CBlockLocator &locator) const;
+
+ /** Find the last common block between this chain and a block index entry. */
+ CBlockIndex *FindFork(CBlockIndex *pindex) const;
};
/** The currently-connected chain of blocks. */
extern CChain chainActive;
-/** The currently best known chain of headers (some of which may be invalid). */
-extern CChain chainMostWork;
-
/** Global variable that points to the active CCoinsView (protected by cs_main) */
extern CCoinsViewCache *pcoinsTip;
diff --git a/src/miner.cpp b/src/miner.cpp
index 708b9248f3..68abc4a6ef 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -52,25 +52,30 @@ void SHA256Transform(void* pstate, void* pinput, const void* pinit)
((uint32_t*)pstate)[i] = ctx.h[i];
}
-// Some explaining would be appreciated
+//
+// Unconfirmed transactions in the memory pool often depend on other
+// transactions in the memory pool. When we select transactions from the
+// pool, we select by highest priority or fee rate, so we might consider
+// transactions that depend on transactions that aren't yet in the block.
+// The COrphan class keeps track of these 'temporary orphans' while
+// CreateBlock is figuring out which transactions to include.
+//
class COrphan
{
public:
const CTransaction* ptx;
set<uint256> setDependsOn;
+ CFeeRate feeRate;
double dPriority;
- double dFeePerKb;
- COrphan(const CTransaction* ptxIn)
+ COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
{
- ptx = ptxIn;
- dPriority = dFeePerKb = 0;
}
void print() const
{
- LogPrintf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
- ptx->GetHash().ToString(), dPriority, dFeePerKb);
+ LogPrintf("COrphan(hash=%s, dPriority=%.1f, fee=%s)\n",
+ ptx->GetHash().ToString(), dPriority, feeRate.ToString());
BOOST_FOREACH(uint256 hash, setDependsOn)
LogPrintf(" setDependsOn %s\n", hash.ToString());
}
@@ -80,8 +85,8 @@ public:
uint64_t nLastBlockTx = 0;
uint64_t nLastBlockSize = 0;
-// We want to sort transactions by priority and fee, so:
-typedef boost::tuple<double, double, const CTransaction*> TxPriority;
+// We want to sort transactions by priority and fee rate, so:
+typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
class TxPriorityCompare
{
bool byFee;
@@ -210,18 +215,15 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
dPriority = tx.ComputePriority(dPriority, nTxSize);
- // This is a more accurate fee-per-kilobyte than is used by the client code, because the
- // client code rounds up the size to the nearest 1K. That's good, because it gives an
- // incentive to create smaller transactions.
- double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0);
+ CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
if (porphan)
{
porphan->dPriority = dPriority;
- porphan->dFeePerKb = dFeePerKb;
+ porphan->feeRate = feeRate;
}
else
- vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &mi->second.GetTx()));
+ vecPriority.push_back(TxPriority(dPriority, feeRate, &mi->second.GetTx()));
}
// Collect transactions into block
@@ -237,7 +239,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
// Take highest priority transaction off the priority queue:
double dPriority = vecPriority.front().get<0>();
- double dFeePerKb = vecPriority.front().get<1>();
+ CFeeRate feeRate = vecPriority.front().get<1>();
const CTransaction& tx = *(vecPriority.front().get<2>());
std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
@@ -254,7 +256,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
continue;
// Skip free transactions if we're past the minimum block size:
- if (fSortedByFee && (dFeePerKb < CTransaction::nMinRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
+ if (fSortedByFee && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
continue;
// Prioritize by fee once past the priority size or we run out of high-priority
@@ -298,8 +300,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if (fPrintPriority)
{
- LogPrintf("priority %.1f feeperkb %.1f txid %s\n",
- dPriority, dFeePerKb, tx.GetHash().ToString());
+ LogPrintf("priority %.1f fee %s txid %s\n",
+ dPriority, feeRate.ToString(), tx.GetHash().ToString());
}
// Add transactions that depend on this one to the priority queue
@@ -312,7 +314,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
porphan->setDependsOn.erase(hash);
if (porphan->setDependsOn.empty())
{
- vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx));
+ vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
}
}
@@ -482,22 +484,22 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
LOCK(cs_main);
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
return error("BitcoinMiner : generated block is stale");
+ }
- // Remove key from key pool
- reservekey.KeepKey();
+ // Remove key from key pool
+ reservekey.KeepKey();
- // Track how many getdata requests this block gets
- {
- LOCK(wallet.cs_wallet);
- wallet.mapRequestCount[pblock->GetHash()] = 0;
- }
-
- // Process this block the same as if we had received it from another node
- CValidationState state;
- if (!ProcessBlock(state, NULL, pblock))
- return error("BitcoinMiner : ProcessBlock, block not accepted");
+ // Track how many getdata requests this block gets
+ {
+ LOCK(wallet.cs_wallet);
+ wallet.mapRequestCount[pblock->GetHash()] = 0;
}
+ // Process this block the same as if we had received it from another node
+ CValidationState state;
+ if (!ProcessBlock(state, NULL, pblock))
+ return error("BitcoinMiner : ProcessBlock, block not accepted");
+
return true;
}
diff --git a/src/net.cpp b/src/net.cpp
index b0e6699ed2..479f77c469 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -45,6 +45,7 @@ static const int MAX_OUTBOUND_CONNECTIONS = 8;
// Global state variables
//
bool fDiscover = true;
+bool fListen = true;
uint64_t nLocalServices = NODE_NETWORK;
CCriticalSection cs_mapLocalHost;
map<CNetAddr, LocalServiceInfo> mapLocalHost;
@@ -96,7 +97,7 @@ unsigned short GetListenPort()
// find 'best' local address for a particular peer
bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
{
- if (fNoListen)
+ if (!fListen)
return false;
int nBestScore = -1;
diff --git a/src/net.h b/src/net.h
index d50cd92dba..9fcdbf802b 100644
--- a/src/net.h
+++ b/src/net.h
@@ -105,6 +105,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
extern bool fDiscover;
+extern bool fListen;
extern uint64_t nLocalServices;
extern uint64_t nLocalHostNonce;
extern CAddrMan addrman;
diff --git a/src/qt/Makefile b/src/qt/Makefile
new file mode 100644
index 0000000000..b9dcf0c599
--- /dev/null
+++ b/src/qt/Makefile
@@ -0,0 +1,9 @@
+.PHONY: FORCE
+all: FORCE
+ $(MAKE) -C .. bitcoin_qt test_bitcoin_qt
+clean: FORCE
+ $(MAKE) -C .. bitcoin_qt_clean test_bitcoin_qt_clean
+check: FORCE
+ $(MAKE) -C .. test_bitcoin_qt_check
+bitcoin-qt bitcoin-qt.exe: FORCE
+ $(MAKE) -C .. bitcoin_qt
diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am
deleted file mode 100644
index 1d85113d78..0000000000
--- a/src/qt/Makefile.am
+++ /dev/null
@@ -1,382 +0,0 @@
-include $(top_srcdir)/src/Makefile.include
-
-AM_CPPFLAGS += -I$(top_srcdir)/src \
- -I$(top_builddir)/src/qt \
- -I$(top_builddir)/src/qt/forms \
- $(PROTOBUF_CFLAGS) \
- $(QR_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_ca@valencia.ts \
- locale/bitcoin_cmn.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_DO.ts \
- locale/bitcoin_es_MX.ts \
- locale/bitcoin_es.ts \
- locale/bitcoin_es_UY.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_gl.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_ka.ts \
- locale/bitcoin_kk_KZ.ts \
- locale/bitcoin_ko_KR.ts \
- locale/bitcoin_ky.ts \
- locale/bitcoin_la.ts \
- locale/bitcoin_lt.ts \
- locale/bitcoin_lv_LV.ts \
- locale/bitcoin_mn.ts \
- locale/bitcoin_ms_MY.ts \
- locale/bitcoin_nb.ts \
- locale/bitcoin_nl.ts \
- locale/bitcoin_pam.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_sah.ts \
- locale/bitcoin_sk.ts \
- locale/bitcoin_sl_SI.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_ur_PK.ts \
- locale/bitcoin_uz@Cyrl.ts \
- locale/bitcoin_vi.ts \
- locale/bitcoin_vi_VN.ts \
- locale/bitcoin_zh_CN.ts \
- locale/bitcoin_zh_HK.ts \
- locale/bitcoin_zh_TW.ts
-
-QT_FORMS_UI = \
- forms/aboutdialog.ui \
- forms/addressbookpage.ui \
- forms/askpassphrasedialog.ui \
- forms/coincontroldialog.ui \
- forms/editaddressdialog.ui \
- forms/helpmessagedialog.ui \
- forms/intro.ui \
- forms/openuridialog.ui \
- forms/optionsdialog.ui \
- forms/overviewpage.ui \
- forms/receivecoinsdialog.ui \
- forms/receiverequestdialog.ui \
- forms/rpcconsole.ui \
- forms/sendcoinsdialog.ui \
- forms/sendcoinsentry.ui \
- forms/signverifymessagedialog.ui \
- forms/transactiondescdialog.ui
-
-QT_MOC_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_coincontroldialog.cpp \
- moc_coincontroltreewidget.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_openuridialog.cpp \
- moc_optionsdialog.cpp \
- moc_optionsmodel.cpp \
- moc_overviewpage.cpp \
- moc_peertablemodel.cpp \
- moc_paymentserver.cpp \
- moc_qvalidatedlineedit.cpp \
- moc_qvaluecombobox.cpp \
- moc_receivecoinsdialog.cpp \
- moc_receiverequestdialog.cpp \
- moc_recentrequeststablemodel.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_utilitydialog.cpp \
- moc_walletframe.cpp \
- moc_walletmodel.cpp \
- moc_walletview.cpp
-
-BITCOIN_MM = \
- macdockiconhandler.mm \
- macnotificationhandler.mm
-
-QT_MOC = \
- bitcoin.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 = \
- addressbookpage.h \
- addresstablemodel.h \
- askpassphrasedialog.h \
- bitcoinaddressvalidator.h \
- bitcoinamountfield.h \
- bitcoingui.h \
- bitcoinunits.h \
- clientmodel.h \
- coincontroldialog.h \
- coincontroltreewidget.h \
- csvmodelwriter.h \
- editaddressdialog.h \
- guiconstants.h \
- guiutil.h \
- intro.h \
- macdockiconhandler.h \
- macnotificationhandler.h \
- monitoreddatamapper.h \
- notificator.h \
- openuridialog.h \
- optionsdialog.h \
- optionsmodel.h \
- overviewpage.h \
- paymentrequestplus.h \
- paymentserver.h \
- peertablemodel.h \
- qvalidatedlineedit.h \
- qvaluecombobox.h \
- receivecoinsdialog.h \
- receiverequestdialog.h \
- recentrequeststablemodel.h \
- rpcconsole.h \
- sendcoinsdialog.h \
- sendcoinsentry.h \
- signverifymessagedialog.h \
- splashscreen.h \
- trafficgraphwidget.h \
- transactiondesc.h \
- transactiondescdialog.h \
- transactionfilterproxy.h \
- transactionrecord.h \
- transactiontablemodel.h \
- transactionview.h \
- utilitydialog.h \
- walletframe.h \
- walletmodel.h \
- walletmodeltransaction.h \
- walletview.h \
- winshutdownmonitor.h
-
-RES_ICONS = \
- res/icons/add.png \
- res/icons/address-book.png \
- res/icons/bitcoin.ico \
- res/icons/bitcoin.png \
- res/icons/bitcoin_testnet.ico \
- res/icons/bitcoin_testnet.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/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/debugwindow.png \
- res/icons/edit.png \
- res/icons/editcopy.png \
- res/icons/editpaste.png \
- res/icons/export.png \
- res/icons/filesave.png \
- res/icons/history.png \
- res/icons/key.png \
- res/icons/lock_closed.png \
- res/icons/lock_open.png \
- res/icons/overview.png \
- res/icons/qrcode.png \
- res/icons/quit.png \
- res/icons/receive.png \
- res/icons/remove.png \
- res/icons/send.png \
- res/icons/synced.png \
- res/icons/toolbar.png \
- res/icons/toolbar_testnet.png \
- res/icons/transaction0.png \
- res/icons/transaction2.png \
- res/icons/transaction_conflicted.png \
- res/icons/tx_inout.png \
- res/icons/tx_input.png \
- res/icons/tx_output.png \
- res/icons/tx_mined.png
-
-BITCOIN_QT_CPP = \
- bitcoin.cpp \
- bitcoinaddressvalidator.cpp \
- bitcoinamountfield.cpp \
- bitcoingui.cpp \
- bitcoinunits.cpp \
- clientmodel.cpp \
- csvmodelwriter.cpp \
- guiutil.cpp \
- intro.cpp \
- monitoreddatamapper.cpp \
- notificator.cpp \
- optionsdialog.cpp \
- optionsmodel.cpp \
- qvalidatedlineedit.cpp \
- qvaluecombobox.cpp \
- rpcconsole.cpp \
- splashscreen.cpp \
- trafficgraphwidget.cpp \
- utilitydialog.cpp \
- winshutdownmonitor.cpp
-
-if ENABLE_WALLET
-BITCOIN_QT_CPP += \
- addressbookpage.cpp \
- addresstablemodel.cpp \
- askpassphrasedialog.cpp \
- coincontroldialog.cpp \
- coincontroltreewidget.cpp \
- editaddressdialog.cpp \
- openuridialog.cpp \
- overviewpage.cpp \
- paymentrequestplus.cpp \
- paymentserver.cpp \
- peertablemodel.cpp \
- receivecoinsdialog.cpp \
- receiverequestdialog.cpp \
- recentrequeststablemodel.cpp \
- sendcoinsdialog.cpp \
- sendcoinsentry.cpp \
- signverifymessagedialog.cpp \
- transactiondesc.cpp \
- transactiondescdialog.cpp \
- transactionfilterproxy.cpp \
- transactionrecord.cpp \
- transactiontablemodel.cpp \
- transactionview.cpp \
- walletframe.cpp \
- walletmodel.cpp \
- walletmodeltransaction.cpp \
- walletview.cpp
-endif
-
-RES_IMAGES = \
- res/images/about.png \
- res/images/splash.png \
- res/images/splash_testnet.png
-
-RES_MOVIES = $(wildcard res/movies/spinner-*.png)
-
-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)
-
-# bitcoin-qt binary #
-bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
- -I$(top_srcdir)/src/qt/forms
-bitcoin_qt_SOURCES = bitcoin.cpp
-if TARGET_DARWIN
- bitcoin_qt_SOURCES += $(BITCOIN_MM)
-endif
-if TARGET_WINDOWS
- bitcoin_qt_SOURCES += $(BITCOIN_RC)
-endif
-bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER)
-if ENABLE_WALLET
-bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
-endif
-bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
- $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
-bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
-
-# 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)
- @test -n $(LUPDATE) || echo "lupdate is required for updating translations"
- @QT_SELECT=$(QT_SELECT) $(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) && QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin -o $(abs_builddir)/$@ $< || \
- echo error: could not build $@
- $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,}
- $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,}
-
-CLEANFILES = $(BUILT_SOURCES) $(QT_QM) $(QT_FORMS_H) *.gcda *.gcno
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index dc9d2afe27..e27f1bff97 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -453,7 +453,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0));
txDummy.vout.push_back(txout);
- if (txout.IsDust(CTransaction::nMinRelayTxFee))
+ if (txout.IsDust(CTransaction::minRelayTxFee))
fDust = true;
}
}
@@ -525,7 +525,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority);
// Fee
- int64_t nFee = nTransactionFee * (1 + (int64_t)nBytes / 1000);
+ int64_t nFee = payTxFee.GetFee(nBytes);
// Min Fee
int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND);
@@ -536,26 +536,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
{
nChange = nAmount - nPayFee - nPayAmount;
- // if sub-cent change is required, the fee must be raised to at least CTransaction::nMinTxFee
- if (nPayFee < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
- {
- if (nChange < CTransaction::nMinTxFee) // change < 0.0001 => simply move all change to fees
- {
- nPayFee += nChange;
- nChange = 0;
- }
- else
- {
- nChange = nChange + nPayFee - CTransaction::nMinTxFee;
- nPayFee = CTransaction::nMinTxFee;
- }
- }
-
// Never create dust outputs; if we would, just add the dust to the fee.
if (nChange > 0 && nChange < CENT)
{
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0));
- if (txout.IsDust(CTransaction::nMinRelayTxFee))
+ if (txout.IsDust(CTransaction::minRelayTxFee))
{
nPayFee += nChange;
nChange = 0;
@@ -610,19 +595,19 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// tool tips
QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "<br /><br />";
- toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)) + "<br /><br />";
+ toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "<br /><br />";
toolTip1 += tr("Can vary +/- 1 byte per input.");
QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "<br /><br />";
toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "<br /><br />";
- toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee));
+ toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK()));
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "<br /><br />";
- toolTip3 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)) + "<br /><br />";
+ toolTip3 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "<br /><br />";
toolTip3 += tr("Amounts below 0.546 times the minimum relay fee are shown as dust.");
QString toolTip4 = tr("This label turns red, if the change is smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "<br /><br />";
- toolTip4 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee));
+ toolTip4 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK()));
l5->setToolTip(toolTip1);
l6->setToolTip(toolTip2);
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index bf737d9b99..1e574e8527 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -113,13 +113,39 @@
</widget>
</item>
<item row="4" column="0">
+ <widget class="QLabel" name="label_berkeleyDBVersion">
+ <property name="text">
+ <string>Using BerkeleyDB version</string>
+ </property>
+ <property name="indent">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="berkeleyDBVersion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Build date</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="5" column="1">
<widget class="QLabel" name="buildDate">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -135,14 +161,14 @@
</property>
</widget>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="6" column="1">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -158,7 +184,7 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_11">
<property name="font">
<font>
@@ -171,14 +197,14 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="8" column="1">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -194,14 +220,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="8" column="1">
+ <item row="9" column="1">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -217,7 +243,7 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
@@ -230,14 +256,14 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current number of blocks</string>
</property>
</widget>
</item>
- <item row="10" column="1">
+ <item row="11" column="1">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -253,14 +279,14 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="11" column="1">
+ <item row="12" column="1">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -276,7 +302,7 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="13" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -289,7 +315,7 @@
</property>
</spacer>
</item>
- <item row="13" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelDebugLogfile">
<property name="font">
<font>
@@ -302,7 +328,7 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="15" column="0">
<widget class="QPushButton" name="openDebugLogfileButton">
<property name="toolTip">
<string>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</string>
@@ -315,7 +341,7 @@
</property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="16" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 1922d228c5..4fe98251d9 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -210,7 +210,7 @@ bool isDust(const QString& address, qint64 amount)
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
CScript script; script.SetDestination(dest);
CTxOut txOut(amount, script);
- return txOut.IsDust(CTransaction::nMinRelayTxFee);
+ return txOut.IsDust(CTransaction::minRelayTxFee);
}
QString HtmlEscape(const QString& str, bool fMultiLine)
diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts
index 687947e3b9..e957a0088e 100644
--- a/src/qt/locale/bitcoin_el_GR.ts
+++ b/src/qt/locale/bitcoin_el_GR.ts
@@ -3,11 +3,11 @@
<name>AboutDialog</name>
<message>
<source>About Bitcoin Core</source>
- <translation type="unfinished"/>
+ <translation>Σχετικά με το Bitcoin Core</translation>
</message>
<message>
<source>&lt;b&gt;Bitcoin Core&lt;/b&gt; version</source>
- <translation type="unfinished"/>
+ <translation>&lt;b&gt;Bitcoin Core&lt;/b&gt; έκδοση</translation>
</message>
<message>
<source>
@@ -29,11 +29,11 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>The Bitcoin Core developers</source>
- <translation type="unfinished"/>
+ <translation>Οι προγραμματιστές του Bitcoin Core</translation>
</message>
<message>
<source>(%1-bit)</source>
- <translation type="unfinished"/>
+ <translation>(%1-bit)</translation>
</message>
</context>
<context>
@@ -128,11 +128,11 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished"/>
+ <translation>Η εξαγωγή απέτυχε</translation>
</message>
<message>
<source>There was an error trying to save the address list to %1.</source>
- <translation type="unfinished"/>
+ <translation>Παρουσιάστηκε σφάλμα κατά την αποθήκευση της λίστας πορτοφολιών στο %1.</translation>
</message>
</context>
<context>
@@ -438,7 +438,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>&amp;About Bitcoin Core</source>
- <translation type="unfinished"/>
+ <translation>&amp;Σχετικά με το Bitcoin Core</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
@@ -494,11 +494,11 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>%1 and %2</source>
- <translation type="unfinished"/>
+ <translation>%1 και %2</translation>
</message>
<message numerus="yes">
<source>%n year(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>%n έτος</numerusform><numerusform>%n έτη</numerusform></translation>
</message>
<message>
<source>%1 behind</source>
@@ -608,11 +608,11 @@ Address: %4
</message>
<message>
<source>Change:</source>
- <translation type="unfinished"/>
+ <translation>Ρέστα:</translation>
</message>
<message>
<source>(un)select all</source>
- <translation type="unfinished"/>
+ <translation>(από)επιλογή όλων</translation>
</message>
<message>
<source>Tree mode</source>
@@ -672,7 +672,7 @@ Address: %4
</message>
<message>
<source>Copy quantity</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή ποσότητας</translation>
</message>
<message>
<source>Copy fee</source>
@@ -684,11 +684,11 @@ Address: %4
</message>
<message>
<source>Copy bytes</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή των byte</translation>
</message>
<message>
<source>Copy priority</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή προτεραιότητας</translation>
</message>
<message>
<source>Copy low output</source>
@@ -696,51 +696,51 @@ Address: %4
</message>
<message>
<source>Copy change</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή των ρέστων</translation>
</message>
<message>
<source>highest</source>
- <translation type="unfinished"/>
+ <translation>ύψιστη</translation>
</message>
<message>
<source>higher</source>
- <translation type="unfinished"/>
+ <translation>υψηλότερη</translation>
</message>
<message>
<source>high</source>
- <translation type="unfinished"/>
+ <translation>ψηλή</translation>
</message>
<message>
<source>medium-high</source>
- <translation type="unfinished"/>
+ <translation>μεσαία-ψηλή</translation>
</message>
<message>
<source>medium</source>
- <translation type="unfinished"/>
+ <translation>μεσαία</translation>
</message>
<message>
<source>low-medium</source>
- <translation type="unfinished"/>
+ <translation>μεσαία-χαμηλή</translation>
</message>
<message>
<source>low</source>
- <translation type="unfinished"/>
+ <translation>χαμηλή</translation>
</message>
<message>
<source>lower</source>
- <translation type="unfinished"/>
+ <translation>χαμηλότερη</translation>
</message>
<message>
<source>lowest</source>
- <translation type="unfinished"/>
+ <translation>χαμηλότατη</translation>
</message>
<message>
<source>(%1 locked)</source>
- <translation type="unfinished"/>
+ <translation>(%1 κλειδωμένο)</translation>
</message>
<message>
<source>none</source>
- <translation type="unfinished"/>
+ <translation>κανένα</translation>
</message>
<message>
<source>Dust</source>
@@ -796,11 +796,12 @@ Address: %4
</message>
<message>
<source>change from %1 (%2)</source>
- <translation type="unfinished"/>
+ <translation>ρέστα από %1 (%2) </translation>
</message>
<message>
<source>(change)</source>
- <translation type="unfinished"/>
+ <translation>(ρέστα)
+</translation>
</message>
</context>
<context>
@@ -815,7 +816,7 @@ Address: %4
</message>
<message>
<source>The label associated with this address list entry</source>
- <translation type="unfinished"/>
+ <translation>Η ετικέτα που συνδέεται με αυτήν την καταχώρηση στο βιβλίο διευθύνσεων</translation>
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
@@ -936,11 +937,11 @@ Address: %4
</message>
<message>
<source>Welcome to Bitcoin Core.</source>
- <translation type="unfinished"/>
+ <translation>Καλώς ήρθατε στο Bitcoin Core.</translation>
</message>
<message>
<source>As this is the first time the program is launched, you can choose where Bitcoin Core will store its data.</source>
- <translation type="unfinished"/>
+ <translation>Καθώς αυτή είναι η πρώτη φορά που εκκινείται το πρόγραμμα, μπορείτε να διαλέξετε πού θα αποθηκεύει το Bitcoin Core τα δεδομένα του.</translation>
</message>
<message>
<source>Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</source>
@@ -1030,7 +1031,7 @@ Address: %4
</message>
<message>
<source>MB</source>
- <translation type="unfinished"/>
+ <translation>MB</translation>
</message>
<message>
<source>Number of script &amp;verification threads</source>
@@ -1082,7 +1083,7 @@ Address: %4
</message>
<message>
<source>Expert</source>
- <translation type="unfinished"/>
+ <translation>Έμπειρος</translation>
</message>
<message>
<source>Enable coin &amp;control features</source>
@@ -1190,7 +1191,7 @@ Address: %4
</message>
<message>
<source>none</source>
- <translation type="unfinished"/>
+ <translation>κανένα</translation>
</message>
<message>
<source>Confirm options reset</source>
@@ -1198,7 +1199,7 @@ Address: %4
</message>
<message>
<source>Client restart required to activate changes.</source>
- <translation type="unfinished"/>
+ <translation>Χρειάζεται επανεκκίνηση του προγράμματος για να ενεργοποιηθούν οι αλλαγές.</translation>
</message>
<message>
<source>Client will be shutdown, do you want to proceed?</source>
@@ -1229,7 +1230,7 @@ Address: %4
</message>
<message>
<source>Available:</source>
- <translation type="unfinished"/>
+ <translation>Διαθέσιμο:</translation>
</message>
<message>
<source>Your current spendable balance</source>
@@ -1370,11 +1371,11 @@ Address: %4
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation type="unfinished"/>
+ <translation>&amp;Αποθήκευση εικόνας...</translation>
</message>
<message>
<source>&amp;Copy Image</source>
- <translation type="unfinished"/>
+ <translation>&amp;Αντιγραφή εικόνας</translation>
</message>
<message>
<source>Save QR Code</source>
@@ -1409,7 +1410,7 @@ Address: %4
</message>
<message>
<source>General</source>
- <translation type="unfinished"/>
+ <translation>Γενικά</translation>
</message>
<message>
<source>Using OpenSSL version</source>
@@ -1425,7 +1426,7 @@ Address: %4
</message>
<message>
<source>Name</source>
- <translation type="unfinished"/>
+ <translation>Όνομα</translation>
</message>
<message>
<source>Number of connections</source>
@@ -1457,11 +1458,11 @@ Address: %4
</message>
<message>
<source>&amp;Network Traffic</source>
- <translation type="unfinished"/>
+ <translation>&amp;Κίνηση δικτύου</translation>
</message>
<message>
<source>&amp;Clear</source>
- <translation type="unfinished"/>
+ <translation>&amp;Εκκαθάριση</translation>
</message>
<message>
<source>Totals</source>
@@ -1536,7 +1537,7 @@ Address: %4
<name>ReceiveCoinsDialog</name>
<message>
<source>&amp;Amount:</source>
- <translation type="unfinished"/>
+ <translation>&amp;Ποσό:</translation>
</message>
<message>
<source>&amp;Label:</source>
@@ -1544,7 +1545,7 @@ Address: %4
</message>
<message>
<source>&amp;Message:</source>
- <translation type="unfinished"/>
+ <translation>&amp;Μήνυμα:</translation>
</message>
<message>
<source>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</source>
@@ -1584,7 +1585,7 @@ Address: %4
</message>
<message>
<source>&amp;Request payment</source>
- <translation type="unfinished"/>
+ <translation>&amp;Αίτηση πληρωμής</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1608,7 +1609,7 @@ Address: %4
</message>
<message>
<source>Copy message</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή μηνύματος</translation>
</message>
<message>
<source>Copy amount</source>
@@ -1631,7 +1632,7 @@ Address: %4
</message>
<message>
<source>&amp;Save Image...</source>
- <translation type="unfinished"/>
+ <translation>&amp;Αποθήκευση εικόνας...</translation>
</message>
<message>
<source>Request payment to %1</source>
@@ -1698,7 +1699,7 @@ Address: %4
</message>
<message>
<source>(no amount)</source>
- <translation type="unfinished"/>
+ <translation>(κανένα ποσό)</translation>
</message>
</context>
<context>
@@ -1717,7 +1718,7 @@ Address: %4
</message>
<message>
<source>automatically selected</source>
- <translation type="unfinished"/>
+ <translation>επιλεγμένο αυτόματα</translation>
</message>
<message>
<source>Insufficient funds!</source>
@@ -1753,7 +1754,7 @@ Address: %4
</message>
<message>
<source>Change:</source>
- <translation type="unfinished"/>
+ <translation>Ρέστα:</translation>
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
@@ -1801,7 +1802,7 @@ Address: %4
</message>
<message>
<source>Copy quantity</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή ποσότητας</translation>
</message>
<message>
<source>Copy amount</source>
@@ -1817,11 +1818,11 @@ Address: %4
</message>
<message>
<source>Copy bytes</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή των byte</translation>
</message>
<message>
<source>Copy priority</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή προτεραιότητας</translation>
</message>
<message>
<source>Copy low output</source>
@@ -1829,15 +1830,15 @@ Address: %4
</message>
<message>
<source>Copy change</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφή των ρέστων</translation>
</message>
<message>
<source>Total Amount %1 (= %2)</source>
- <translation type="unfinished"/>
+ <translation>Ολικό Ποσό %1 (= %2)</translation>
</message>
<message>
<source>or</source>
- <translation type="unfinished"/>
+ <translation>ή</translation>
</message>
<message>
<source>The recipient address is not valid, please recheck.</source>
@@ -1940,7 +1941,7 @@ Address: %4
</message>
<message>
<source>Remove this entry</source>
- <translation type="unfinished"/>
+ <translation>Αφαίρεση αυτής της καταχώρησης</translation>
</message>
<message>
<source>Message:</source>
@@ -1975,11 +1976,11 @@ Address: %4
<name>ShutdownWindow</name>
<message>
<source>Bitcoin Core is shutting down...</source>
- <translation type="unfinished"/>
+ <translation>Το Bitcoin Core τερματίζεται...</translation>
</message>
<message>
<source>Do not shut down the computer until this window disappears.</source>
- <translation type="unfinished"/>
+ <translation>Μην απενεργοποιήσετε τον υπολογιστή μέχρι να κλείσει αυτό το παράθυρο.</translation>
</message>
</context>
<context>
@@ -2133,7 +2134,7 @@ Address: %4
</message>
<message>
<source>The Bitcoin Core developers</source>
- <translation type="unfinished"/>
+ <translation>Οι προγραμματιστές του Bitcoin Core</translation>
</message>
<message>
<source>[testnet]</source>
@@ -2341,11 +2342,11 @@ Address: %4
</message>
<message>
<source>Offline</source>
- <translation type="unfinished"/>
+ <translation>Offline</translation>
</message>
<message>
<source>Unconfirmed</source>
- <translation type="unfinished"/>
+ <translation>Ανεπιβεβαίωτες</translation>
</message>
<message>
<source>Confirming (%1 of %2 recommended confirmations)</source>
@@ -2484,19 +2485,19 @@ Address: %4
</message>
<message>
<source>Export Transaction History</source>
- <translation type="unfinished"/>
+ <translation>Εξαγωγή Ιστορικού Συναλλαγών</translation>
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished"/>
+ <translation>Η Εξαγωγή Απέτυχε</translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
- <translation type="unfinished"/>
+ <translation>Yπήρξε σφάλμα κατά την προσπάθεια αποθήκευσης του ιστορικού συναλλαγών στο %1.</translation>
</message>
<message>
<source>Exporting Successful</source>
- <translation type="unfinished"/>
+ <translation>Επιτυχής εξαγωγή</translation>
</message>
<message>
<source>The transaction history was successfully saved to %1.</source>
@@ -2547,7 +2548,7 @@ Address: %4
<name>WalletFrame</name>
<message>
<source>No wallet has been loaded.</source>
- <translation type="unfinished"/>
+ <translation>Δεν έχει φορτωθεί πορτοφόλι</translation>
</message>
</context>
<context>
@@ -2585,7 +2586,7 @@ Address: %4
</message>
<message>
<source>The wallet data was successfully saved to %1.</source>
- <translation type="unfinished"/>
+ <translation>Τα δεδομένα πορτοφολιού αποθηκεύτηκαν με επιτυχία στο %1.</translation>
</message>
<message>
<source>Backup Successful</source>
@@ -2801,11 +2802,11 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>(default: 1)</source>
- <translation type="unfinished"/>
+ <translation>(προεπιλογή: 1)</translation>
</message>
<message>
<source>(default: wallet.dat)</source>
- <translation type="unfinished"/>
+ <translation>(προεπιλογή: wallet.dat)</translation>
</message>
<message>
<source>&lt;category&gt; can be:</source>
@@ -2841,7 +2842,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>Connection options:</source>
- <translation type="unfinished"/>
+ <translation>Επιλογές σύνδεσης:</translation>
</message>
<message>
<source>Corrupted block database detected</source>
@@ -3045,7 +3046,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>Wallet options:</source>
- <translation type="unfinished"/>
+ <translation>Επιλογές πορτοφολιού:</translation>
</message>
<message>
<source>Warning: Deprecated argument -debugnet ignored, use -debug=net</source>
@@ -3229,7 +3230,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>on startup</source>
- <translation type="unfinished"/>
+ <translation>κατά την εκκίνηση</translation>
</message>
<message>
<source>version</source>
diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts
index 1a46c6ae6c..2ad31e911b 100644
--- a/src/qt/locale/bitcoin_sl_SI.ts
+++ b/src/qt/locale/bitcoin_sl_SI.ts
@@ -344,7 +344,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Modify configuration options for Bitcoin</source>
- <translation type="unfinished"/>
+ <translation>Spremeni konfiguracijo nastavitev za Bitcoin</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -1144,7 +1144,7 @@ Naslov: %4
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation type="unfinished"/>
+ <translation>Vmesnik uporabnika &amp;jezik:</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting Bitcoin.</source>
@@ -1487,11 +1487,11 @@ Naslov: %4
</message>
<message>
<source>Welcome to the Bitcoin RPC console.</source>
- <translation type="unfinished"/>
+ <translation>Dobrodošli na Bitcoin RPC konzoli.</translation>
</message>
<message>
<source>Use up and down arrows to navigate history, and &lt;b&gt;Ctrl-L&lt;/b&gt; to clear screen.</source>
- <translation type="unfinished"/>
+ <translation>Uporabi puščice za gor in dol za navigacijo po zgodovini in &lt;b&gt;Ctrl-L&lt;/b&gt; za izbris izpisa na ekranu.</translation>
</message>
<message>
<source>Type &lt;b&gt;help&lt;/b&gt; for an overview of available commands.</source>
@@ -1847,7 +1847,7 @@ Naslov: %4
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation type="unfinished"/>
+ <translation>Celotni znesek presega vaše stanje, ko je zaračunana 1% provizija.</translation>
</message>
<message>
<source>Duplicate address found, can only send to each address once per send operation.</source>
@@ -2626,7 +2626,7 @@ Naslov: %4
</message>
<message>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation type="unfinished"/>
+ <translation>Povežite se z vozliščem za pridobitev naslovov uporabnikov in nato prekinite povezavo.</translation>
</message>
<message>
<source>Specify your own public address</source>
@@ -2638,7 +2638,7 @@ Naslov: %4
</message>
<message>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
- <translation type="unfinished"/>
+ <translation>Število sekund za težavo pri vzpostavitvi povezave med uporabniki (privzeto: 86400)</translation>
</message>
<message>
<source>An error occurred while setting up the RPC port %u for listening on IPv4: %s</source>
@@ -3268,11 +3268,11 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>Unable to bind to %s on this computer (bind returned error %d, %s)</source>
- <translation type="unfinished"/>
+ <translation>Nemogoče je povezati s/z %s na tem računalniku (povezava je vrnila napaka %d, %s)</translation>
</message>
<message>
<source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation type="unfinished"/>
+ <translation>Omogoči DNS poizvedbe za -addnode, -seednode in -connect.</translation>
</message>
<message>
<source>Loading addresses...</source>
@@ -3296,27 +3296,27 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>Invalid -proxy address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Neveljaven -proxy naslov: &apos;%s&apos;</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Neznano omrežje določeno v -onlynet: &apos;%s&apos;.</translation>
</message>
<message>
<source>Unknown -socks proxy version requested: %i</source>
- <translation type="unfinished"/>
+ <translation>Neznano -socks zahtevan zastopnik različice: %i</translation>
</message>
<message>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Nemogoče rešiti -bind naslova: &apos;%s&apos;</translation>
</message>
<message>
<source>Cannot resolve -externalip address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Nemogoče rešiti -externalip naslova: &apos;%s&apos;</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Neveljavna količina za -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<source>Invalid amount</source>
@@ -3344,7 +3344,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>Cannot write default address</source>
- <translation type="unfinished"/>
+ <translation>Ni mogoče zapisati privzetega naslova</translation>
</message>
<message>
<source>Rescanning...</source>
@@ -3356,7 +3356,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<source>To use the %s option</source>
- <translation type="unfinished"/>
+ <translation>Za uporabo %s opcije</translation>
</message>
<message>
<source>Error</source>
@@ -3366,7 +3366,9 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<source>You must set rpcpassword=&lt;password&gt; in the configuration file:
%s
If the file does not exist, create it with owner-readable-only file permissions.</source>
- <translation type="unfinished"/>
+ <translation>Potrebno je nastaviti rpcpassword=&lt;password&gt; v nastavitveni datoteki:
+%s
+Če datoteka ne obstaja jo ustvarite z dovoljenjem, da jo lahko bere samo uporabnik.</translation>
</message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts
index 96c49b12d0..54e15a75e0 100644
--- a/src/qt/locale/bitcoin_th_TH.ts
+++ b/src/qt/locale/bitcoin_th_TH.ts
@@ -35,7 +35,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<name>AddressBookPage</name>
<message>
<source>Double-click to edit address or label</source>
- <translation>ดับเบิลคลิก เพื่อแก้ไขที่อยู่ หรือชื่อ</translation>
+ <translation>ดับเบิ้ลคลิก เพื่อแก้ไขที่อยู่ หรือชื่อ</translation>
</message>
<message>
<source>Create a new address</source>
@@ -75,7 +75,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>&amp;Delete</source>
- <translation>ลบ</translation>
+ <translation>&amp;ลบ</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -119,7 +119,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation type="unfinished"/>
+ <translation>คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -165,7 +165,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<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 type="unfinished"/>
+ <translation>ใส่รหัสผ่านใหม่ให้กับกระเป๋าเงิน. &lt;br/&gt; กรุณาใช้รหัสผ่านของ &lt;b&gt; 10 หรือแบบสุ่มมากกว่าตัวอักษร &lt;/ b&gt; หรือ &lt;b&gt; แปดหรือมากกว่าคำ &lt;/ b&gt;</translation>
</message>
<message>
<source>Encrypt wallet</source>
@@ -173,7 +173,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished"/>
+ <translation>การดำเนินการนี้ต้องมีรหัสผ่านกระเป๋าเงินของคุณเพื่อปลดล็อคกระเป๋าเงิน</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -181,7 +181,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation type="unfinished"/>
+ <translation>การดำเนินการนี้ต้องมีรหัสผ่านกระเป๋าเงินของคุณในการถอดรหัสกระเป๋าเงิน</translation>
</message>
<message>
<source>Decrypt wallet</source>
@@ -229,7 +229,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation type="unfinished"/>
+ <translation>กระเป๋าเงินเข้ารหัสล้มเหลวเนื่องจากข้อผิดพลาดภายใน กระเป๋าเงินของคุณไม่ได้เข้ารหัส</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
@@ -237,15 +237,15 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Wallet unlock failed</source>
- <translation type="unfinished"/>
+ <translation>ปลดล็อคกระเป๋าเงินล้มเหลว</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation type="unfinished"/>
+ <translation>ป้อนรหัสผ่านสำหรับการถอดรหัสกระเป๋าเงินไม่ถูกต้อง</translation>
</message>
<message>
<source>Wallet decryption failed</source>
- <translation type="unfinished"/>
+ <translation>ถอดรหัสกระเป๋าเงินล้มเหลว</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
@@ -260,11 +260,11 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Synchronizing with network...</source>
- <translation type="unfinished"/>
+ <translation>กำลังทำข้อมูลให้ตรงกันกับเครือข่าย ...</translation>
</message>
<message>
<source>&amp;Overview</source>
- <translation type="unfinished"/>
+ <translation>&amp;ภาพรวม</translation>
</message>
<message>
<source>Node</source>
@@ -272,15 +272,15 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Show general overview of wallet</source>
- <translation type="unfinished"/>
+ <translation>แสดงภาพรวมทั่วไปของกระเป๋าเงิน</translation>
</message>
<message>
<source>&amp;Transactions</source>
- <translation type="unfinished"/>
+ <translation>&amp;การทำรายการ</translation>
</message>
<message>
<source>Browse transaction history</source>
- <translation type="unfinished"/>
+ <translation>เรียกดูประวัติการทำธุรกรรม</translation>
</message>
<message>
<source>E&amp;xit</source>
@@ -288,11 +288,11 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Quit application</source>
- <translation type="unfinished"/>
+ <translation>ออกจากโปรแกรม</translation>
</message>
<message>
<source>Show information about Bitcoin</source>
- <translation type="unfinished"/>
+ <translation>แสดงข้อมูลเกี่ยวกับ Bitcoin</translation>
</message>
<message>
<source>About &amp;Qt</source>
@@ -304,7 +304,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>&amp;Options...</source>
- <translation type="unfinished"/>
+ <translation>&amp;ตัวเลือก...</translation>
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
@@ -352,7 +352,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation type="unfinished"/>
+ <translation>เปลี่ยนรหัสผ่านที่ใช้สำหรับการเข้ารหัสกระเป๋าเงิน</translation>
</message>
<message>
<source>&amp;Debug window</source>
@@ -404,23 +404,23 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>&amp;File</source>
- <translation type="unfinished"/>
+ <translation>&amp;ไฟล์</translation>
</message>
<message>
<source>&amp;Settings</source>
- <translation type="unfinished"/>
+ <translation>&amp;การตั้งค่า</translation>
</message>
<message>
<source>&amp;Help</source>
- <translation type="unfinished"/>
+ <translation>&amp;ช่วยเหลือ</translation>
</message>
<message>
<source>Tabs toolbar</source>
- <translation type="unfinished"/>
+ <translation>แถบเครื่องมือ</translation>
</message>
<message>
<source>[testnet]</source>
- <translation type="unfinished"/>
+ <translation>[testnet]</translation>
</message>
<message>
<source>Bitcoin Core</source>
@@ -460,7 +460,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation type="unfinished"><numerusform></numerusform></translation>
+ <translation><numerusform>%n ที่ใช้งานการเชื่อมต่อกับเครือข่าย Bitcoin</numerusform></translation>
</message>
<message>
<source>No block source available...</source>
@@ -520,19 +520,19 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<source>Up to date</source>
- <translation type="unfinished"/>
+ <translation>ทันสมัย</translation>
</message>
<message>
<source>Catching up...</source>
- <translation type="unfinished"/>
+ <translation>จับได้...</translation>
</message>
<message>
<source>Sent transaction</source>
- <translation type="unfinished"/>
+ <translation>รายการที่ส่ง</translation>
</message>
<message>
<source>Incoming transaction</source>
- <translation type="unfinished"/>
+ <translation>การทำรายการขาเข้า</translation>
</message>
<message>
<source>Date: %1
@@ -544,11 +544,11 @@ Address: %4
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished"/>
+ <translation>ระเป๋าเงินถูก &lt;b&gt;เข้ารหัส&lt;/b&gt; และในขณะนี้ &lt;b&gt;ปลดล็อคแล้ว&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation type="unfinished"/>
+ <translation>กระเป๋าเงินถูก &lt;b&gt;เข้ารหัส&lt;/b&gt; และในปัจจุบัน &lt;b&gt;ล็อค &lt;/b&gt;</translation>
</message>
<message>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
@@ -797,11 +797,11 @@ Address: %4
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation type="unfinished"/>
+ <translation>แก้ไขที่อยู่</translation>
</message>
<message>
<source>&amp;Label</source>
- <translation type="unfinished"/>
+ <translation>&amp;ชื่อ</translation>
</message>
<message>
<source>The label associated with this address list entry</source>
@@ -813,27 +813,27 @@ Address: %4
</message>
<message>
<source>&amp;Address</source>
- <translation type="unfinished"/>
+ <translation>&amp;ที่อยู่</translation>
</message>
<message>
<source>New receiving address</source>
- <translation type="unfinished"/>
+ <translation>ที่อยู่ผู้รับใหม่</translation>
</message>
<message>
<source>New sending address</source>
- <translation type="unfinished"/>
+ <translation>ที่อยู่ผู้ส่งใหม่</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation type="unfinished"/>
+ <translation>แก้ไขที่อยู่ผู้รับ</translation>
</message>
<message>
<source>Edit sending address</source>
- <translation type="unfinished"/>
+ <translation>แก้ไขที่อยู่ผู้ส่ง</translation>
</message>
<message>
<source>The entered address &quot;%1&quot; is already in the address book.</source>
- <translation type="unfinished"/>
+ <translation>ป้อนที่อยู่ &quot;%1&quot; ที่มีอยู่แล้วในสมุดที่อยู่</translation>
</message>
<message>
<source>The entered address &quot;%1&quot; is not a valid Bitcoin address.</source>
@@ -841,11 +841,11 @@ Address: %4
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation type="unfinished"/>
+ <translation>ไม่สามารถปลดล็อคกระเป๋าเงิน</translation>
</message>
<message>
<source>New key generation failed.</source>
- <translation type="unfinished"/>
+ <translation>สร้างกุญแจใหม่ล้มเหลว</translation>
</message>
</context>
<context>
@@ -992,7 +992,7 @@ Address: %4
<name>OptionsDialog</name>
<message>
<source>Options</source>
- <translation type="unfinished"/>
+ <translation>ตัวเลือก</translation>
</message>
<message>
<source>&amp;Main</source>
@@ -1207,7 +1207,7 @@ Address: %4
<name>OverviewPage</name>
<message>
<source>Form</source>
- <translation type="unfinished"/>
+ <translation>รูป</translation>
</message>
<message>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
@@ -1251,7 +1251,7 @@ Address: %4
</message>
<message>
<source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
- <translation type="unfinished"/>
+ <translation>&lt;b&gt;รายการทำธุรกรรมล่าสุด&lt;/b&gt;</translation>
</message>
<message>
<source>out of sync</source>
@@ -1695,7 +1695,7 @@ Address: %4
<name>SendCoinsDialog</name>
<message>
<source>Send Coins</source>
- <translation type="unfinished"/>
+ <translation>ส่งเหรียญ</translation>
</message>
<message>
<source>Coin Control Features</source>
@@ -2127,7 +2127,7 @@ Address: %4
</message>
<message>
<source>[testnet]</source>
- <translation type="unfinished"/>
+ <translation>[testnet]</translation>
</message>
</context>
<context>
@@ -2494,7 +2494,7 @@ Address: %4
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation type="unfinished"/>
+ <translation>คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv)</translation>
</message>
<message>
<source>Confirmed</source>
@@ -2544,7 +2544,7 @@ Address: %4
<name>WalletModel</name>
<message>
<source>Send Coins</source>
- <translation type="unfinished"/>
+ <translation>ส่งเหรียญ</translation>
</message>
</context>
<context>
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 96464d2cc0..1cbf5f8810 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -14,7 +14,7 @@
#include "monitoreddatamapper.h"
#include "optionsmodel.h"
-#include "main.h" // for CTransaction::nMinTxFee and MAX_SCRIPTCHECK_THREADS
+#include "main.h" // for CTransaction::minTxFee and MAX_SCRIPTCHECK_THREADS
#include "netbase.h"
#include "txdb.h" // for -dbcache defaults
@@ -101,7 +101,7 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
#endif
ui->unit->setModel(new BitcoinUnits(this));
- ui->transactionFee->setSingleStep(CTransaction::nMinTxFee);
+ ui->transactionFee->setSingleStep(CTransaction::minTxFee.GetFeePerK());
/* Widget-to-option mapper */
mapper = new MonitoredDataMapper(this);
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 051098315d..f3a5f37bb3 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -94,7 +94,7 @@ void OptionsModel::Init()
#ifdef ENABLE_WALLET
if (!settings.contains("nTransactionFee"))
settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE);
- nTransactionFee = settings.value("nTransactionFee").toLongLong(); // if -paytxfee is set, this will be overridden later in init.cpp
+ payTxFee = CFeeRate(settings.value("nTransactionFee").toLongLong()); // if -paytxfee is set, this will be overridden later in init.cpp
if (mapArgs.count("-paytxfee"))
addOverriddenOption("-paytxfee");
@@ -187,15 +187,16 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return settings.value("nSocksVersion", 5);
#ifdef ENABLE_WALLET
- case Fee:
- // Attention: Init() is called before nTransactionFee is set in AppInit2()!
+ case Fee: {
+ // Attention: Init() is called before payTxFee is set in AppInit2()!
// To ensure we can change the fee on-the-fly update our QSetting when
// opening OptionsDialog, which queries Fee via the mapper.
- if (nTransactionFee != settings.value("nTransactionFee").toLongLong())
- settings.setValue("nTransactionFee", (qint64)nTransactionFee);
- // Todo: Consider to revert back to use just nTransactionFee here, if we don't want
+ if (!(payTxFee == CFeeRate(settings.value("nTransactionFee").toLongLong(), 1000)))
+ settings.setValue("nTransactionFee", (qint64)payTxFee.GetFeePerK());
+ // Todo: Consider to revert back to use just payTxFee here, if we don't want
// -paytxfee to update our QSettings!
return settings.value("nTransactionFee");
+ }
case SpendZeroConfChange:
return settings.value("bSpendZeroConfChange");
#endif
@@ -284,12 +285,14 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
}
break;
#ifdef ENABLE_WALLET
- case Fee: // core option - can be changed on-the-fly
+ case Fee: { // core option - can be changed on-the-fly
// Todo: Add is valid check and warn via message, if not
- nTransactionFee = value.toLongLong();
- settings.setValue("nTransactionFee", (qint64)nTransactionFee);
+ qint64 nTransactionFee = value.toLongLong();
+ payTxFee = CFeeRate(nTransactionFee, 1000);
+ settings.setValue("nTransactionFee", nTransactionFee);
emit transactionFeeChanged(nTransactionFee);
break;
+ }
case SpendZeroConfChange:
if (settings.value("bSpendZeroConfChange") != value) {
settings.setValue("bSpendZeroConfChange", value);
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 20551591c3..9241f9dc3c 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -561,7 +561,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
// Extract and check amounts
CTxOut txOut(sendingTo.second, sendingTo.first);
- if (txOut.IsDust(CTransaction::nMinRelayTxFee)) {
+ if (txOut.IsDust(CTransaction::minRelayTxFee)) {
emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
CClientUIInterface::MSG_ERROR);
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index db5ce639b1..981d063c49 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -49,8 +49,8 @@ public:
/** Pull a full list of peers from vNodes into our cache */
void refreshPeers() {
- TRY_LOCK(cs_vNodes, lockNodes);
{
+ TRY_LOCK(cs_vNodes, lockNodes);
if (!lockNodes)
{
// skip the refresh if we can't immediately get the lock
@@ -70,8 +70,8 @@ public:
}
// if we can, retrieve the CNodeStateStats for each node.
- TRY_LOCK(cs_main, lockMain);
{
+ TRY_LOCK(cs_main, lockMain);
if (lockMain)
{
BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 3b7d37ff39..0d3e11f4ac 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -15,7 +15,11 @@
#include "util.h"
#include "json/json_spirit_value.h"
+#ifdef ENABLE_WALLET
+#include <db_cxx.h>
+#endif
#include <openssl/crypto.h>
+
#include <QKeyEvent>
#include <QScrollBar>
#include <QThread>
@@ -216,8 +220,14 @@ RPCConsole::RPCConsole(QWidget *parent) :
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
- // set OpenSSL version label
+ // set library version labels
ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
+#ifdef ENABLE_WALLET
+ ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
+#else
+ ui->label_berkeleyDBVersion->hide();
+ ui->berkeleyDBVersion->hide();
+#endif
startExecutor();
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
diff --git a/src/qt/test/Makefile b/src/qt/test/Makefile
new file mode 100644
index 0000000000..a02f86b62a
--- /dev/null
+++ b/src/qt/test/Makefile
@@ -0,0 +1,6 @@
+all:
+ $(MAKE) -C ../../ test_bitcoin_qt
+clean:
+ $(MAKE) -C ../../ test_bitcoin_qt_clean
+check:
+ $(MAKE) -C ../../ test_bitcoin_qt_check
diff --git a/src/qt/test/Makefile.am b/src/qt/test/Makefile.am
deleted file mode 100644
index 2461b5ff4d..0000000000
--- a/src/qt/test/Makefile.am
+++ /dev/null
@@ -1,46 +0,0 @@
-include $(top_srcdir)/src/Makefile.include
-
-AM_CPPFLAGS += -I$(top_srcdir)/src \
- -I$(top_srcdir)/src/qt \
- -I$(top_builddir)/src/qt \
- $(PROTOBUF_CFLAGS) \
- $(QR_CFLAGS)
-bin_PROGRAMS = test_bitcoin-qt
-TESTS = test_bitcoin-qt
-
-TEST_QT_MOC_CPP = moc_uritests.cpp
-
-if ENABLE_WALLET
-TEST_QT_MOC_CPP += moc_paymentservertests.cpp
-endif
-
-TEST_QT_H = \
- uritests.h \
- paymentrequestdata.h \
- paymentservertests.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 \
- $(TEST_QT_H)
-if ENABLE_WALLET
-test_bitcoin_qt_SOURCES += \
- paymentservertests.cpp
-endif
-
-nodist_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
-
-test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER)
-if ENABLE_WALLET
-test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
-endif
-test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
- $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
- $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
-test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
-
-CLEANFILES = $(BUILT_SOURCES) *.gcda *.gcno
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 37d82ec063..87ff3db584 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -231,12 +231,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return AmountExceedsBalance;
}
- if((total + nTransactionFee) > nBalance)
- {
- transaction.setTransactionFee(nTransactionFee);
- return SendCoinsReturn(AmountWithFeeExceedsBalance);
- }
-
{
LOCK2(cs_main, wallet->cs_wallet);
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index 4f3c39ce9b..b89a95ad11 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -176,6 +176,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "verifychain" && n > 1) ConvertTo<int64_t>(params[1]);
if (strMethod == "keypoolrefill" && n > 0) ConvertTo<int64_t>(params[0]);
if (strMethod == "getrawmempool" && n > 0) ConvertTo<bool>(params[0]);
+ if (strMethod == "estimatefee" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "estimatepriority" && n > 0) ConvertTo<boost::int64_t>(params[0]);
return params;
}
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index edf91023dc..837f5336c4 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -15,6 +15,7 @@
#endif
#include <stdint.h>
+#include <boost/assign/list_of.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
@@ -626,3 +627,63 @@ Value submitblock(const Array& params, bool fHelp)
return Value::null;
}
+
+Value estimatefee(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "estimatefee nblocks\n"
+ "\nEstimates the approximate fee per kilobyte\n"
+ "needed for a transaction to get confirmed\n"
+ "within nblocks blocks.\n"
+ "\nArguments:\n"
+ "1. nblocks (numeric)\n"
+ "\nResult:\n"
+ "n : (numeric) estimated fee-per-kilobyte\n"
+ "\n"
+ "-1.0 is returned if not enough transactions and\n"
+ "blocks have been observed to make an estimate.\n"
+ "\nExample:\n"
+ + HelpExampleCli("estimatefee", "6")
+ );
+
+ RPCTypeCheck(params, boost::assign::list_of(int_type));
+
+ int nBlocks = params[0].get_int();
+ if (nBlocks < 1)
+ nBlocks = 1;
+
+ CFeeRate feeRate = mempool.estimateFee(nBlocks);
+ if (feeRate == CFeeRate(0))
+ return -1.0;
+
+ return ValueFromAmount(feeRate.GetFeePerK());
+}
+
+Value estimatepriority(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "estimatepriority nblocks\n"
+ "\nEstimates the approximate priority\n"
+ "a zero-fee transaction needs to get confirmed\n"
+ "within nblocks blocks.\n"
+ "\nArguments:\n"
+ "1. nblocks (numeric)\n"
+ "\nResult:\n"
+ "n : (numeric) estimated priority\n"
+ "\n"
+ "-1.0 is returned if not enough transactions and\n"
+ "blocks have been observed to make an estimate.\n"
+ "\nExample:\n"
+ + HelpExampleCli("estimatepriority", "6")
+ );
+
+ RPCTypeCheck(params, boost::assign::list_of(int_type));
+
+ int nBlocks = params[0].get_int();
+ if (nBlocks < 1)
+ nBlocks = 1;
+
+ return mempool.estimatePriority(nBlocks);
+}
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index a1793e2e43..77e0e09ec3 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -81,9 +81,9 @@ Value getinfo(const Array& params, bool fHelp)
}
if (pwalletMain && pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
- obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
+ obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
#endif
- obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee)));
+ obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK())));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj;
}
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 63eed09b64..0eca55a472 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -368,7 +368,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
obj.push_back(Pair("timeoffset", 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("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee)));
+ obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK())));
Array localAddresses;
{
LOCK(cs_mapLocalHost);
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 2534a9dcf4..d4ceb7f995 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -254,7 +254,7 @@ static const CRPCCommand vRPCCommands[] =
{ "getblocktemplate", &getblocktemplate, true, false, false },
{ "getmininginfo", &getmininginfo, true, false, false },
{ "getnetworkhashps", &getnetworkhashps, true, false, false },
- { "submitblock", &submitblock, false, false, false },
+ { "submitblock", &submitblock, false, true, false },
/* Raw transactions */
{ "createrawtransaction", &createrawtransaction, false, false, false },
@@ -268,6 +268,8 @@ static const CRPCCommand vRPCCommands[] =
{ "createmultisig", &createmultisig, true, true , false },
{ "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */
{ "verifymessage", &verifymessage, false, false, false },
+ { "estimatefee", &estimatefee, true, true, false },
+ { "estimatepriority", &estimatepriority, true, true, false },
#ifdef ENABLE_WALLET
/* Wallet */
diff --git a/src/rpcserver.h b/src/rpcserver.h
index e8cd2cd0fc..73e8b9426c 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -133,6 +133,8 @@ extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool f
extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value estimatepriority(const json_spirit::Array& params, bool fHelp);
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);
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index e3b35dbb04..f376ab6b63 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -1883,7 +1883,7 @@ Value settxfee(const Array& params, bool fHelp)
if (params[0].get_real() != 0.0)
nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
- nTransactionFee = nAmount;
+ payTxFee = CFeeRate(nAmount, 1000);
return true;
}
diff --git a/src/script.cpp b/src/script.cpp
index ac6d4b316f..381e84d0b7 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -208,14 +208,13 @@ const char* GetOpName(opcodetype opcode)
case OP_NOP9 : return "OP_NOP9";
case OP_NOP10 : return "OP_NOP10";
+ case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
+ // Note:
+ // The template matching params OP_SMALLDATA/etc are defined in opcodetype enum
+ // as kind of implementation hack, they are *NOT* real opcodes. If found in real
+ // Script, just let the default: case deal with them.
- // template matching params
- case OP_PUBKEYHASH : return "OP_PUBKEYHASH";
- case OP_PUBKEY : return "OP_PUBKEY";
- case OP_SMALLDATA : return "OP_SMALLDATA";
-
- case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
default:
return "OP_UNKNOWN";
}
diff --git a/src/test/Makefile b/src/test/Makefile
new file mode 100644
index 0000000000..87bf73fec9
--- /dev/null
+++ b/src/test/Makefile
@@ -0,0 +1,6 @@
+all:
+ $(MAKE) -C .. bitcoin_test
+clean:
+ $(MAKE) -C .. bitcoin_test_clean
+check:
+ $(MAKE) -C .. bitcoin_test_check
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
deleted file mode 100644
index cde3a31e2f..0000000000
--- a/src/test/Makefile.am
+++ /dev/null
@@ -1,77 +0,0 @@
-include $(top_srcdir)/src/Makefile.include
-
-AM_CPPFLAGS += -I$(top_srcdir)/src
-
-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 \
- data/sighash.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_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
- $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
-if ENABLE_WALLET
-test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
-endif
-test_bitcoin_LDADD += $(BDB_LIBS)
-
-test_bitcoin_SOURCES = \
- bignum.h \
- alert_tests.cpp \
- allocator_tests.cpp \
- base32_tests.cpp \
- base58_tests.cpp \
- base64_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 \
- main_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 \
- uint256_tests.cpp \
- util_tests.cpp \
- scriptnum_tests.cpp \
- sighash_tests.cpp \
- $(JSON_TEST_FILES) $(RAW_TEST_FILES)
-
-if ENABLE_WALLET
-test_bitcoin_SOURCES += \
- accounting_tests.cpp \
- wallet_tests.cpp \
- rpc_wallet_tests.cpp
-endif
-
-nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES)
-
-CLEANFILES = *.gcda *.gcno $(BUILT_SOURCES)
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 64c9eac73d..4bf01d4848 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -6,6 +6,8 @@
#include "core.h"
#include "txmempool.h"
+#include <boost/circular_buffer.hpp>
+
using namespace std;
CTxMemPoolEntry::CTxMemPoolEntry()
@@ -35,12 +37,311 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
return dResult;
}
+//
+// Keep track of fee/priority for transactions confirmed within N blocks
+//
+class CBlockAverage
+{
+private:
+ boost::circular_buffer<CFeeRate> feeSamples;
+ boost::circular_buffer<double> prioritySamples;
+
+ template<typename T> std::vector<T> buf2vec(boost::circular_buffer<T> buf) const
+ {
+ std::vector<T> vec(buf.begin(), buf.end());
+ return vec;
+ }
+
+public:
+ CBlockAverage() : feeSamples(100), prioritySamples(100) { }
+
+ void RecordFee(const CFeeRate& feeRate) {
+ feeSamples.push_back(feeRate);
+ }
+
+ void RecordPriority(double priority) {
+ prioritySamples.push_back(priority);
+ }
+
+ size_t FeeSamples() const { return feeSamples.size(); }
+ size_t GetFeeSamples(std::vector<CFeeRate>& insertInto) const
+ {
+ BOOST_FOREACH(const CFeeRate& f, feeSamples)
+ insertInto.push_back(f);
+ return feeSamples.size();
+ }
+ size_t PrioritySamples() const { return prioritySamples.size(); }
+ size_t GetPrioritySamples(std::vector<double>& insertInto) const
+ {
+ BOOST_FOREACH(double d, prioritySamples)
+ insertInto.push_back(d);
+ return prioritySamples.size();
+ }
+
+ // Used as belt-and-suspenders check when reading to detect
+ // file corruption
+ bool AreSane(const std::vector<CFeeRate>& vecFee)
+ {
+ BOOST_FOREACH(CFeeRate fee, vecFee)
+ {
+ if (fee < CFeeRate(0))
+ return false;
+ if (fee.GetFee(1000) > CTransaction::minRelayTxFee.GetFee(1000) * 10000)
+ return false;
+ }
+ return true;
+ }
+ bool AreSane(const std::vector<double> vecPriority)
+ {
+ BOOST_FOREACH(double priority, vecPriority)
+ {
+ if (priority < 0)
+ return false;
+ }
+ return true;
+ }
+
+ void Write(CAutoFile& fileout) const
+ {
+ std::vector<CFeeRate> vecFee = buf2vec(feeSamples);
+ fileout << vecFee;
+ std::vector<double> vecPriority = buf2vec(prioritySamples);
+ fileout << vecPriority;
+ }
+
+ void Read(CAutoFile& filein) {
+ std::vector<CFeeRate> vecFee;
+ filein >> vecFee;
+ if (AreSane(vecFee))
+ feeSamples.insert(feeSamples.end(), vecFee.begin(), vecFee.end());
+ else
+ throw runtime_error("Corrupt fee value in estimates file.");
+ std::vector<double> vecPriority;
+ filein >> vecPriority;
+ if (AreSane(vecPriority))
+ prioritySamples.insert(prioritySamples.end(), vecPriority.begin(), vecPriority.end());
+ else
+ throw runtime_error("Corrupt priority value in estimates file.");
+ if (feeSamples.size() + prioritySamples.size() > 0)
+ LogPrint("estimatefee", "Read %d fee samples and %d priority samples\n",
+ feeSamples.size(), prioritySamples.size());
+ }
+};
+
+class CMinerPolicyEstimator
+{
+private:
+ // Records observed averages transactions that confirmed within one block, two blocks,
+ // three blocks etc.
+ std::vector<CBlockAverage> history;
+ std::vector<CFeeRate> sortedFeeSamples;
+ std::vector<double> sortedPrioritySamples;
+
+ int nBestSeenHeight;
+
+ // nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
+ // nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
+ void seenTxConfirm(CFeeRate feeRate, double dPriority, int nBlocksAgo)
+ {
+ // Last entry records "everything else".
+ int nBlocksTruncated = min(nBlocksAgo, (int) history.size() - 1);
+ assert(nBlocksTruncated >= 0);
+
+ // We need to guess why the transaction was included in a block-- either
+ // because it is high-priority or because it has sufficient fees.
+ bool sufficientFee = (feeRate > CTransaction::minRelayTxFee);
+ bool sufficientPriority = AllowFree(dPriority);
+ const char* assignedTo = "unassigned";
+ if (sufficientFee && !sufficientPriority)
+ {
+ history[nBlocksTruncated].RecordFee(feeRate);
+ assignedTo = "fee";
+ }
+ else if (sufficientPriority && !sufficientFee)
+ {
+ history[nBlocksTruncated].RecordPriority(dPriority);
+ assignedTo = "priority";
+ }
+ else
+ {
+ // Neither or both fee and priority sufficient to get confirmed:
+ // don't know why they got confirmed.
+ }
+ LogPrint("estimatefee", "Seen TX confirm: %s : %s fee/%g priority, took %d blocks\n",
+ assignedTo, feeRate.ToString(), dPriority, nBlocksAgo);
+ }
+
+public:
+ CMinerPolicyEstimator(int nEntries) : nBestSeenHeight(0)
+ {
+ history.resize(nEntries);
+ }
+
+ void seenBlock(const std::vector<CTxMemPoolEntry>& entries, int nBlockHeight)
+ {
+ if (nBlockHeight <= nBestSeenHeight)
+ {
+ // Ignore side chains and re-orgs; assuming they are random
+ // they don't affect the estimate.
+ // And if an attacker can re-org the chain at will, then
+ // you've got much bigger problems than "attacker can influence
+ // transaction fees."
+ return;
+ }
+ nBestSeenHeight = nBlockHeight;
+
+ // Fill up the history buckets based on how long transactions took
+ // to confirm.
+ std::vector<std::vector<const CTxMemPoolEntry*> > entriesByConfirmations;
+ entriesByConfirmations.resize(history.size());
+ BOOST_FOREACH(const CTxMemPoolEntry& entry, entries)
+ {
+ // How many blocks did it take for miners to include this transaction?
+ int delta = nBlockHeight - entry.GetHeight();
+ if (delta <= 0)
+ {
+ // Re-org made us lose height, this should only happen if we happen
+ // to re-org on a difficulty transition point: very rare!
+ continue;
+ }
+ if ((delta-1) >= (int)history.size())
+ delta = history.size(); // Last bucket is catch-all
+ entriesByConfirmations[delta-1].push_back(&entry);
+ }
+ for (size_t i = 0; i < entriesByConfirmations.size(); i++)
+ {
+ std::vector<const CTxMemPoolEntry*> &e = entriesByConfirmations.at(i);
+ // Insert at most 10 random entries per bucket, otherwise a single block
+ // can dominate an estimate:
+ if (e.size() > 10) {
+ std::random_shuffle(e.begin(), e.end());
+ e.resize(10);
+ }
+ BOOST_FOREACH(const CTxMemPoolEntry* entry, e)
+ {
+ // Fees are stored and reported as BTC-per-kb:
+ CFeeRate feeRate(entry->GetFee(), entry->GetTxSize());
+ double dPriority = entry->GetPriority(entry->GetHeight()); // Want priority when it went IN
+ seenTxConfirm(feeRate, dPriority, i);
+ }
+ }
+ for (size_t i = 0; i < history.size(); i++) {
+ if (history[i].FeeSamples() + history[i].PrioritySamples() > 0)
+ LogPrint("estimatefee", "estimates: for confirming within %d blocks based on %d/%d samples, fee=%s, prio=%g\n",
+ i,
+ history[i].FeeSamples(), history[i].PrioritySamples(),
+ estimateFee(i+1).ToString(), estimatePriority(i+1));
+ }
+ sortedFeeSamples.clear();
+ sortedPrioritySamples.clear();
+ }
+
+ // Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
+ CFeeRate estimateFee(int nBlocksToConfirm)
+ {
+ nBlocksToConfirm--;
+
+ if (nBlocksToConfirm < 0 || nBlocksToConfirm >= (int)history.size())
+ return CFeeRate(0);
+
+ if (sortedFeeSamples.size() == 0)
+ {
+ for (size_t i = 0; i < history.size(); i++)
+ history.at(i).GetFeeSamples(sortedFeeSamples);
+ std::sort(sortedFeeSamples.begin(), sortedFeeSamples.end(),
+ std::greater<CFeeRate>());
+ }
+ if (sortedFeeSamples.size() == 0)
+ return CFeeRate(0);
+
+ int nBucketSize = history.at(nBlocksToConfirm).FeeSamples();
+
+ // Estimates should not increase as number of confirmations goes up,
+ // but the estimates are noisy because confirmations happen discretely
+ // in blocks. To smooth out the estimates, use all samples in the history
+ // and use the nth highest where n is (number of samples in previous bucket +
+ // half the samples in nBlocksToConfirm bucket):
+ size_t nPrevSize = 0;
+ for (int i = 0; i < nBlocksToConfirm; i++)
+ nPrevSize += history.at(i).FeeSamples();
+ size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1);
+ return sortedFeeSamples[index];
+ }
+ double estimatePriority(int nBlocksToConfirm)
+ {
+ nBlocksToConfirm--;
+
+ if (nBlocksToConfirm < 0 || nBlocksToConfirm >= (int)history.size())
+ return -1;
+
+ if (sortedPrioritySamples.size() == 0)
+ {
+ for (size_t i = 0; i < history.size(); i++)
+ history.at(i).GetPrioritySamples(sortedPrioritySamples);
+ std::sort(sortedPrioritySamples.begin(), sortedPrioritySamples.end(),
+ std::greater<double>());
+ }
+ if (sortedPrioritySamples.size() == 0)
+ return -1.0;
+
+ int nBucketSize = history.at(nBlocksToConfirm).PrioritySamples();
+
+ // Estimates should not increase as number of confirmations needed goes up,
+ // but the estimates are noisy because confirmations happen discretely
+ // in blocks. To smooth out the estimates, use all samples in the history
+ // and use the nth highest where n is (number of samples in previous buckets +
+ // half the samples in nBlocksToConfirm bucket).
+ size_t nPrevSize = 0;
+ for (int i = 0; i < nBlocksToConfirm; i++)
+ nPrevSize += history.at(i).PrioritySamples();
+ size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1);
+ return sortedPrioritySamples[index];
+ }
+
+ void Write(CAutoFile& fileout) const
+ {
+ fileout << nBestSeenHeight;
+ fileout << history.size();
+ BOOST_FOREACH(const CBlockAverage& entry, history)
+ {
+ entry.Write(fileout);
+ }
+ }
+
+ void Read(CAutoFile& filein)
+ {
+ filein >> nBestSeenHeight;
+ size_t numEntries;
+ filein >> numEntries;
+ history.clear();
+ for (size_t i = 0; i < numEntries; i++)
+ {
+ CBlockAverage entry;
+ entry.Read(filein);
+ history.push_back(entry);
+ }
+ }
+};
+
+
CTxMemPool::CTxMemPool()
{
// Sanity checks off by default for performance, because otherwise
// accepting transactions becomes O(N^2) where N is the number
// of transactions in the pool
fSanityCheck = false;
+
+ // 25 blocks is a compromise between using a lot of disk/memory and
+ // trying to give accurate estimates to people who might be willing
+ // to wait a day or two to save a fraction of a penny in fees.
+ // Confirmation times for very-low-fee transactions that take more
+ // than an hour or three to confirm are highly variable.
+ minerPolicyEstimator = new CMinerPolicyEstimator(25);
+}
+
+CTxMemPool::~CTxMemPool()
+{
+ delete minerPolicyEstimator;
}
void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
@@ -128,6 +429,28 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
}
}
+// Called when a block is connected. Removes from mempool and updates the miner fee estimator.
+void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
+ std::list<CTransaction>& conflicts)
+{
+ LOCK(cs);
+ std::vector<CTxMemPoolEntry> entries;
+ BOOST_FOREACH(const CTransaction& tx, vtx)
+ {
+ uint256 hash = tx.GetHash();
+ if (mapTx.count(hash))
+ entries.push_back(mapTx[hash]);
+ }
+ minerPolicyEstimator->seenBlock(entries, nBlockHeight);
+ BOOST_FOREACH(const CTransaction& tx, vtx)
+ {
+ std::list<CTransaction> dummy;
+ remove(tx, dummy, false);
+ removeConflicts(tx, conflicts);
+ }
+}
+
+
void CTxMemPool::clear()
{
LOCK(cs);
@@ -195,6 +518,53 @@ bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
return true;
}
+CFeeRate CTxMemPool::estimateFee(int nBlocks) const
+{
+ LOCK(cs);
+ return minerPolicyEstimator->estimateFee(nBlocks);
+}
+double CTxMemPool::estimatePriority(int nBlocks) const
+{
+ LOCK(cs);
+ return minerPolicyEstimator->estimatePriority(nBlocks);
+}
+
+bool
+CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
+{
+ try {
+ LOCK(cs);
+ fileout << 99900; // version required to read: 0.9.99 or later
+ fileout << CLIENT_VERSION; // version that wrote the file
+ minerPolicyEstimator->Write(fileout);
+ }
+ catch (std::exception &e) {
+ LogPrintf("CTxMemPool::WriteFeeEstimates() : unable to write policy estimator data (non-fatal)");
+ return false;
+ }
+ return true;
+}
+
+bool
+CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
+{
+ try {
+ int nVersionRequired, nVersionThatWrote;
+ filein >> nVersionRequired >> nVersionThatWrote;
+ if (nVersionRequired > CLIENT_VERSION)
+ return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired);
+
+ LOCK(cs);
+ minerPolicyEstimator->Read(filein);
+ }
+ catch (std::exception &e) {
+ LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)");
+ return false;
+ }
+ return true;
+}
+
+
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) {
diff --git a/src/txmempool.h b/src/txmempool.h
index 4509e95778..b2915aa842 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -11,6 +11,13 @@
#include "core.h"
#include "sync.h"
+inline bool AllowFree(double dPriority)
+{
+ // Large (in bytes) low-priority (new, small-coin) transactions
+ // need a fee.
+ return dPriority > COIN * 144 / 250;
+}
+
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
@@ -41,6 +48,8 @@ public:
unsigned int GetHeight() const { return nHeight; }
};
+class CMinerPolicyEstimator;
+
/*
* CTxMemPool stores valid-according-to-the-current-best-chain
* transactions that may be included in the next block.
@@ -56,6 +65,7 @@ class CTxMemPool
private:
bool fSanityCheck; // Normally false, true if -checkmempool or -regtest
unsigned int nTransactionsUpdated;
+ CMinerPolicyEstimator* minerPolicyEstimator;
public:
mutable CCriticalSection cs;
@@ -63,6 +73,7 @@ public:
std::map<COutPoint, CInPoint> mapNextTx;
CTxMemPool();
+ ~CTxMemPool();
/*
* If sanity-checking is turned on, check makes sure the pool is
@@ -76,6 +87,8 @@ public:
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry);
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
+ void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
+ std::list<CTransaction>& conflicts);
void clear();
void queryHashes(std::vector<uint256>& vtxid);
void pruneSpent(const uint256& hash, CCoins &coins);
@@ -95,6 +108,16 @@ public:
}
bool lookup(uint256 hash, CTransaction& result) const;
+
+ // Estimate fee rate needed to get into the next
+ // nBlocks
+ CFeeRate estimateFee(int nBlocks) const;
+ // Estimate priority needed to get into the next
+ // nBlocks
+ double estimatePriority(int nBlocks) const;
+ // Write/Read estimates to disk
+ bool WriteFeeEstimates(CAutoFile& fileout) const;
+ bool ReadFeeEstimates(CAutoFile& filein);
};
/** CCoinsView that brings transactions from a memorypool into view.
diff --git a/src/util.cpp b/src/util.cpp
index 336ef31725..d106b03230 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -94,7 +94,6 @@ bool fPrintToDebugLog = true;
bool fDaemon = false;
bool fServer = false;
string strMiscWarning;
-bool fNoListen = false;
bool fLogTimestamps = false;
volatile bool fReopenDebugLog = false;
CClientUIInterface uiInterface;
diff --git a/src/util.h b/src/util.h
index ffcb20d822..b09f9bb15e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -100,7 +100,6 @@ extern bool fPrintToConsole;
extern bool fPrintToDebugLog;
extern bool fServer;
extern std::string strMiscWarning;
-extern bool fNoListen;
extern bool fLogTimestamps;
extern volatile bool fReopenDebugLog;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 89604f96ac..ef0b442e1a 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -16,7 +16,7 @@
using namespace std;
// Settings
-int64_t nTransactionFee = DEFAULT_TRANSACTION_FEE;
+CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
bool bSpendZeroConfChange = true;
//////////////////////////////////////////////////////////////////////////////
@@ -1233,7 +1233,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
{
LOCK2(cs_main, cs_wallet);
{
- nFeeRet = nTransactionFee;
+ nFeeRet = payTxFee.GetFeePerK();
while (true)
{
wtxNew.vin.clear();
@@ -1246,7 +1246,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
{
CTxOut txout(s.second, s.first);
- if (txout.IsDust(CTransaction::nMinRelayTxFee))
+ if (txout.IsDust(CTransaction::minRelayTxFee))
{
strFailReason = _("Transaction amount too small");
return false;
@@ -1272,16 +1272,6 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
}
int64_t nChange = nValueIn - nValue - nFeeRet;
- // The following if statement should be removed once enough miners
- // have upgraded to the 0.9 GetMinFee() rules. Until then, this avoids
- // creating free transactions that have change outputs less than
- // CENT bitcoins.
- if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
- {
- int64_t nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
- nChange -= nMoveToFee;
- nFeeRet += nMoveToFee;
- }
if (nChange > 0)
{
@@ -1317,7 +1307,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
// Never create dust outputs; if we would, just
// add the dust to the fee.
- if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
+ if (newTxOut.IsDust(CTransaction::minRelayTxFee))
{
nFeeRet += nChange;
reservekey.ReturnKey();
@@ -1355,7 +1345,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
dPriority = wtxNew.ComputePriority(dPriority, nBytes);
// Check that enough fee is included
- int64_t nPayFee = nTransactionFee * (1 + (int64_t)nBytes / 1000);
+ int64_t nPayFee = payTxFee.GetFee(nBytes);
bool fAllowFree = AllowFree(dPriority);
int64_t nMinFee = GetMinFee(wtxNew, nBytes, fAllowFree, GMF_SEND);
if (nFeeRet < max(nPayFee, nMinFee))
@@ -1464,7 +1454,7 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nV
// Check amount
if (nValue <= 0)
return _("Invalid amount");
- if (nValue + nTransactionFee > GetBalance())
+ if (nValue > GetBalance())
return _("Insufficient funds");
// Parse Bitcoin address
diff --git a/src/wallet.h b/src/wallet.h
index d9d071c2b9..274c31157c 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -24,7 +24,7 @@
#include <vector>
// Settings
-extern int64_t nTransactionFee;
+extern CFeeRate payTxFee;
extern bool bSpendZeroConfChange;
// -paytxfee default
@@ -143,27 +143,26 @@ public:
CWallet()
{
- nWalletVersion = FEATURE_BASE;
- nWalletMaxVersion = FEATURE_BASE;
- fFileBacked = false;
- nMasterKeyMaxID = 0;
- pwalletdbEncryption = NULL;
- nOrderPosNext = 0;
- nNextResend = 0;
- nLastResend = 0;
- nTimeFirstKey = 0;
+ SetNull();
}
CWallet(std::string strWalletFileIn)
{
- nWalletVersion = FEATURE_BASE;
- nWalletMaxVersion = FEATURE_BASE;
+ SetNull();
+
strWalletFile = strWalletFileIn;
fFileBacked = true;
+ }
+ void SetNull()
+ {
+ nWalletVersion = FEATURE_BASE;
+ nWalletMaxVersion = FEATURE_BASE;
+ fFileBacked = false;
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
nOrderPosNext = 0;
nNextResend = 0;
nLastResend = 0;
+ nTimeFirstKey = 0;
}
std::map<uint256, CWalletTx> mapWallet;