aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac11
-rwxr-xr-xcontrib/devtools/check-doc.py2
-rw-r--r--depends/packages/fontconfig.mk6
-rw-r--r--src/chainparams.cpp14
-rw-r--r--src/dbwrapper.cpp6
-rw-r--r--src/leveldb/db/memtable.cc2
-rw-r--r--src/leveldb/db/version_set.cc2
-rw-r--r--src/leveldb/port/atomic_pointer.h47
-rw-r--r--src/leveldb/port/port_example.h4
-rw-r--r--src/leveldb/port/port_posix.cc14
-rw-r--r--src/leveldb/port/port_posix.h1
-rw-r--r--src/leveldb/port/port_posix_sse.cc19
-rw-r--r--src/leveldb/port/port_win.cc11
-rw-r--r--src/leveldb/port/port_win.h1
-rw-r--r--src/leveldb/util/crc32c.cc4
-rw-r--r--src/leveldb/util/logging.cc2
-rw-r--r--src/net.cpp31
-rw-r--r--src/net.h19
-rw-r--r--src/net_processing.cpp11
-rw-r--r--src/qt/forms/sendcoinsdialog.ui2
-rw-r--r--src/qt/intro.cpp4
-rw-r--r--src/qt/locale/bitcoin_en.ts2
-rw-r--r--src/wallet/wallet.cpp12
23 files changed, 135 insertions, 92 deletions
diff --git a/configure.ac b/configure.ac
index aea5d7160c..ba523d3762 100644
--- a/configure.ac
+++ b/configure.ac
@@ -258,14 +258,13 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[CXXFLAGS="$CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
-
- # Check for optional instruction set support. Enabling these does _not_ imply that all code will
- # be compiled with them, rather that specific objects/libs may use them after checking for runtime
- # compatibility.
- AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
-
fi
+# Check for optional instruction set support. Enabling these does _not_ imply that all code will
+# be compiled with them, rather that specific objects/libs may use them after checking for runtime
+# compatibility.
+AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
+
TEMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
AC_MSG_CHECKING(for assembler crc32 support)
diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py
index 150f368513..3b7a8f9a61 100755
--- a/contrib/devtools/check-doc.py
+++ b/contrib/devtools/check-doc.py
@@ -21,7 +21,7 @@ CMD_GREP_DOCS = r"egrep -r -I 'HelpMessageOpt\(\"\-[^\"=]+?(=|\")' %s" % (CMD_RO
REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"')
REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")')
# list unsupported, deprecated and duplicate args as they need no documentation
-SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags', '-blockminsize', '-dbcrashratio'])
+SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags', '-blockminsize', '-dbcrashratio', '-forcecompactdb'])
def main():
used = check_output(CMD_GREP_ARGS, shell=True)
diff --git a/depends/packages/fontconfig.mk b/depends/packages/fontconfig.mk
index fb97e0b9ec..12695db4b9 100644
--- a/depends/packages/fontconfig.mk
+++ b/depends/packages/fontconfig.mk
@@ -13,7 +13,13 @@ define $(package)_config_cmds
$($(package)_autoconf)
endef
+# 2.12.1 uses CHAR_WIDTH which is reserved and clashes with some glibc versions, but newer versions of fontconfig
+# have broken makefiles which needlessly attempt to re-generate headers with gperf.
+# Instead, change all uses of CHAR_WIDTH, and disable the rule that forces header re-generation.
+# This can be removed once the upstream build is fixed.
define $(package)_build_cmds
+ sed -i 's/CHAR_WIDTH/CHARWIDTH/g' fontconfig/fontconfig.h src/fcobjshash.gperf src/fcobjs.h src/fcobjshash.h && \
+ sed -i 's/fcobjshash.h: fcobjshash.gperf/fcobjshash.h:/' src/Makefile && \
$(MAKE)
endef
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 02c8abb100..2021ec51db 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -162,11 +162,11 @@ public:
};
chainTxData = ChainTxData{
- // Data as of block 00000000000000000166d612d5595e2b1cd88d71d695fc580af64d8da8658c23 (height 446482).
- 1483472411, // * UNIX timestamp of last known number of transactions
- 184495391, // * total number of transactions between genesis and that timestamp
+ // Data as of block 000000000000000000d97e53664d17967bd4ee50b23abb92e54a34eb222d15ae (height 478913).
+ 1501801925, // * UNIX timestamp of last known number of transactions
+ 243756039, // * total number of transactions between genesis and that timestamp
// (the tx=... number in the SetBestChain debug.log lines)
- 3.2 // * estimated number of transactions per second after that timestamp
+ 3.1 // * estimated number of transactions per second after that timestamp
};
}
};
@@ -250,9 +250,9 @@ public:
};
chainTxData = ChainTxData{
- // Data as of block 00000000c2872f8f8a8935c8e3c5862be9038c97d4de2cf37ed496991166928a (height 1063660)
- 1483546230,
- 12834668,
+ // Data as of block 00000000000001c200b9790dc637d3bb141fe77d155b966ed775b17e109f7c6c (height 1156179)
+ 1501802953,
+ 14706531,
0.15
};
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index ba9e21cc1f..3626e0177f 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -115,6 +115,12 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
dbwrapper_private::HandleError(status);
LogPrintf("Opened LevelDB successfully\n");
+ if (GetBoolArg("-forcecompactdb", false)) {
+ LogPrintf("Starting database compaction of %s\n", path.string());
+ pdb->CompactRange(nullptr, nullptr);
+ LogPrintf("Finished database compaction of %s\n", path.string());
+ }
+
// The base-case obfuscation key, which is a noop.
obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
diff --git a/src/leveldb/db/memtable.cc b/src/leveldb/db/memtable.cc
index bfec0a7e7a..287afdbdcb 100644
--- a/src/leveldb/db/memtable.cc
+++ b/src/leveldb/db/memtable.cc
@@ -101,7 +101,7 @@ void MemTable::Add(SequenceNumber s, ValueType type,
p += 8;
p = EncodeVarint32(p, val_size);
memcpy(p, value.data(), val_size);
- assert((p + val_size) - buf == encoded_len);
+ assert(p + val_size == buf + encoded_len);
table_.Insert(buf);
}
diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc
index b1256f90e1..2cb6d80ed3 100644
--- a/src/leveldb/db/version_set.cc
+++ b/src/leveldb/db/version_set.cc
@@ -20,7 +20,7 @@
namespace leveldb {
-static int TargetFileSize(const Options* options) {
+static size_t TargetFileSize(const Options* options) {
return options->max_file_size;
}
diff --git a/src/leveldb/port/atomic_pointer.h b/src/leveldb/port/atomic_pointer.h
index 1c4c7aafc6..d79a02230d 100644
--- a/src/leveldb/port/atomic_pointer.h
+++ b/src/leveldb/port/atomic_pointer.h
@@ -46,6 +46,30 @@
namespace leveldb {
namespace port {
+// AtomicPointer based on <cstdatomic> if available
+#if defined(LEVELDB_ATOMIC_PRESENT)
+class AtomicPointer {
+ private:
+ std::atomic<void*> rep_;
+ public:
+ AtomicPointer() { }
+ explicit AtomicPointer(void* v) : rep_(v) { }
+ inline void* Acquire_Load() const {
+ return rep_.load(std::memory_order_acquire);
+ }
+ inline void Release_Store(void* v) {
+ rep_.store(v, std::memory_order_release);
+ }
+ inline void* NoBarrier_Load() const {
+ return rep_.load(std::memory_order_relaxed);
+ }
+ inline void NoBarrier_Store(void* v) {
+ rep_.store(v, std::memory_order_relaxed);
+ }
+};
+
+#else
+
// Define MemoryBarrier() if available
// Windows on x86
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
@@ -142,28 +166,6 @@ class AtomicPointer {
}
};
-// AtomicPointer based on <cstdatomic>
-#elif defined(LEVELDB_ATOMIC_PRESENT)
-class AtomicPointer {
- private:
- std::atomic<void*> rep_;
- public:
- AtomicPointer() { }
- explicit AtomicPointer(void* v) : rep_(v) { }
- inline void* Acquire_Load() const {
- return rep_.load(std::memory_order_acquire);
- }
- inline void Release_Store(void* v) {
- rep_.store(v, std::memory_order_release);
- }
- inline void* NoBarrier_Load() const {
- return rep_.load(std::memory_order_relaxed);
- }
- inline void NoBarrier_Store(void* v) {
- rep_.store(v, std::memory_order_relaxed);
- }
-};
-
// Atomic pointer based on sparc memory barriers
#elif defined(__sparcv9) && defined(__GNUC__)
class AtomicPointer {
@@ -229,6 +231,7 @@ class AtomicPointer {
#error Please implement AtomicPointer for this platform.
#endif
+#endif
#undef LEVELDB_HAVE_MEMORY_BARRIER
#undef ARCH_CPU_X86_FAMILY
diff --git a/src/leveldb/port/port_example.h b/src/leveldb/port/port_example.h
index 97bd669a5e..5b1d027de5 100644
--- a/src/leveldb/port/port_example.h
+++ b/src/leveldb/port/port_example.h
@@ -129,6 +129,10 @@ extern bool Snappy_Uncompress(const char* input_data, size_t input_length,
// The concatenation of all "data[0,n-1]" fragments is the heap profile.
extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg);
+// Determine whether a working accelerated crc32 implementation exists
+// Returns true if AcceleratedCRC32C is safe to call
+bool HasAcceleratedCRC32C();
+
// Extend the CRC to include the first n bytes of buf.
//
// Returns zero if the CRC cannot be extended using acceleration, else returns
diff --git a/src/leveldb/port/port_posix.cc b/src/leveldb/port/port_posix.cc
index 30e8007ae3..ec39e92195 100644
--- a/src/leveldb/port/port_posix.cc
+++ b/src/leveldb/port/port_posix.cc
@@ -8,6 +8,10 @@
#include <stdio.h>
#include <string.h>
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__GNUC__)
+#include <cpuid.h>
+#endif
+
namespace leveldb {
namespace port {
@@ -49,5 +53,15 @@ void InitOnce(OnceType* once, void (*initializer)()) {
PthreadCall("once", pthread_once(once, initializer));
}
+bool HasAcceleratedCRC32C() {
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__GNUC__)
+ unsigned int eax, ebx, ecx, edx;
+ __get_cpuid(1, &eax, &ebx, &ecx, &edx);
+ return (ecx & (1 << 20)) != 0;
+#else
+ return false;
+#endif
+}
+
} // namespace port
} // namespace leveldb
diff --git a/src/leveldb/port/port_posix.h b/src/leveldb/port/port_posix.h
index 7e8213b22e..d85fa5d63f 100644
--- a/src/leveldb/port/port_posix.h
+++ b/src/leveldb/port/port_posix.h
@@ -152,6 +152,7 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
return false;
}
+bool HasAcceleratedCRC32C();
uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size);
} // namespace port
diff --git a/src/leveldb/port/port_posix_sse.cc b/src/leveldb/port/port_posix_sse.cc
index 1e519ba0b6..2d49c21dd8 100644
--- a/src/leveldb/port/port_posix_sse.cc
+++ b/src/leveldb/port/port_posix_sse.cc
@@ -19,7 +19,6 @@
#include <intrin.h>
#elif defined(__GNUC__) && defined(__SSE4_2__)
#include <nmmintrin.h>
-#include <cpuid.h>
#endif
#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
@@ -48,20 +47,6 @@ static inline uint64_t LE_LOAD64(const uint8_t *p) {
#endif // defined(_M_X64) || defined(__x86_64__)
-static inline bool HaveSSE42() {
-#if defined(_MSC_VER)
- int cpu_info[4];
- __cpuid(cpu_info, 1);
- return (cpu_info[2] & (1 << 20)) != 0;
-#elif defined(__GNUC__)
- unsigned int eax, ebx, ecx, edx;
- __get_cpuid(1, &eax, &ebx, &ecx, &edx);
- return (ecx & (1 << 20)) != 0;
-#else
- return false;
-#endif
-}
-
#endif // defined(LEVELDB_PLATFORM_POSIX_SSE)
// For further improvements see Intel publication at:
@@ -70,10 +55,6 @@ uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) {
#if !defined(LEVELDB_PLATFORM_POSIX_SSE)
return 0;
#else
- static bool have = HaveSSE42();
- if (!have) {
- return 0;
- }
const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
const uint8_t *e = p + size;
diff --git a/src/leveldb/port/port_win.cc b/src/leveldb/port/port_win.cc
index 1b0f060a19..1be9e8d5b0 100644
--- a/src/leveldb/port/port_win.cc
+++ b/src/leveldb/port/port_win.cc
@@ -32,6 +32,7 @@
#include <windows.h>
#include <cassert>
+#include <intrin.h>
namespace leveldb {
namespace port {
@@ -143,5 +144,15 @@ void AtomicPointer::NoBarrier_Store(void* v) {
rep_ = v;
}
+bool HasAcceleratedCRC32C() {
+#if defined(__x86_64__) || defined(__i386__)
+ int cpu_info[4];
+ __cpuid(cpu_info, 1);
+ return (cpu_info[2] & (1 << 20)) != 0;
+#else
+ return false;
+#endif
+}
+
}
}
diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h
index 5009004822..e8bf46ef27 100644
--- a/src/leveldb/port/port_win.h
+++ b/src/leveldb/port/port_win.h
@@ -168,6 +168,7 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
return false;
}
+bool HasAcceleratedCRC32C();
uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size);
}
diff --git a/src/leveldb/util/crc32c.cc b/src/leveldb/util/crc32c.cc
index edd61cfd6f..b3f40eeeed 100644
--- a/src/leveldb/util/crc32c.cc
+++ b/src/leveldb/util/crc32c.cc
@@ -288,6 +288,10 @@ static inline uint32_t LE_LOAD32(const uint8_t *p) {
// Determine if the CPU running this program can accelerate the CRC32C
// calculation.
static bool CanAccelerateCRC32C() {
+ if (!port::HasAcceleratedCRC32C())
+ return false;
+
+ // Double-check that the accelerated implementation functions correctly.
// port::AcceleretedCRC32C returns zero when unable to accelerate.
static const char kTestCRCBuffer[] = "TestCRCBuffer";
static const char kBufSize = sizeof(kTestCRCBuffer) - 1;
diff --git a/src/leveldb/util/logging.cc b/src/leveldb/util/logging.cc
index ca6b324403..db6160c8f1 100644
--- a/src/leveldb/util/logging.cc
+++ b/src/leveldb/util/logging.cc
@@ -49,7 +49,7 @@ bool ConsumeDecimalNumber(Slice* in, uint64_t* val) {
uint64_t v = 0;
int digits = 0;
while (!in->empty()) {
- char c = (*in)[0];
+ unsigned char c = (*in)[0];
if (c >= '0' && c <= '9') {
++digits;
const int delta = (c - '0');
diff --git a/src/net.cpp b/src/net.cpp
index d4a36a0306..ca9a173abe 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2210,12 +2210,10 @@ CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSe
nReceiveFloodSize = 0;
semOutbound = NULL;
semAddnode = NULL;
- nMaxConnections = 0;
- nMaxOutbound = 0;
- nMaxAddnode = 0;
- nBestHeight = 0;
- clientInterface = NULL;
flagInterruptMsgProc = false;
+
+ Options connOptions;
+ Init(connOptions);
}
NodeId CConnman::GetNewNodeId()
@@ -2254,30 +2252,15 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<C
return fBound;
}
-bool CConnman::Start(CScheduler& scheduler, Options connOptions)
+bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
{
+ Init(connOptions);
+
nTotalBytesRecv = 0;
nTotalBytesSent = 0;
nMaxOutboundTotalBytesSentInCycle = 0;
nMaxOutboundCycleStartTime = 0;
- nRelevantServices = connOptions.nRelevantServices;
- nLocalServices = connOptions.nLocalServices;
- nMaxConnections = connOptions.nMaxConnections;
- nMaxOutbound = std::min((connOptions.nMaxOutbound), nMaxConnections);
- nMaxAddnode = connOptions.nMaxAddnode;
- nMaxFeeler = connOptions.nMaxFeeler;
-
- nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
- nReceiveFloodSize = connOptions.nReceiveFloodSize;
-
- nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
- nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
-
- SetBestHeight(connOptions.nBestHeight);
-
- clientInterface = connOptions.uiInterface;
-
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) {
if (clientInterface) {
clientInterface->ThreadSafeMessageBox(
@@ -2287,8 +2270,6 @@ bool CConnman::Start(CScheduler& scheduler, Options connOptions)
return false;
}
- vWhitelistedRange = connOptions.vWhitelistedRange;
-
for (const auto& strDest : connOptions.vSeedNodes) {
AddOneShot(strDest);
}
diff --git a/src/net.h b/src/net.h
index 1c9413c1dd..93a76fc093 100644
--- a/src/net.h
+++ b/src/net.h
@@ -146,9 +146,26 @@ public:
std::vector<CSubNet> vWhitelistedRange;
std::vector<CService> vBinds, vWhiteBinds;
};
+
+ void Init(const Options& connOptions) {
+ nLocalServices = connOptions.nLocalServices;
+ nRelevantServices = connOptions.nRelevantServices;
+ nMaxConnections = connOptions.nMaxConnections;
+ nMaxOutbound = std::min(connOptions.nMaxOutbound, connOptions.nMaxConnections);
+ nMaxAddnode = connOptions.nMaxAddnode;
+ nMaxFeeler = connOptions.nMaxFeeler;
+ nBestHeight = connOptions.nBestHeight;
+ clientInterface = connOptions.uiInterface;
+ nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
+ nReceiveFloodSize = connOptions.nReceiveFloodSize;
+ nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
+ nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
+ vWhitelistedRange = connOptions.vWhitelistedRange;
+ }
+
CConnman(uint64_t seed0, uint64_t seed1);
~CConnman();
- bool Start(CScheduler& scheduler, Options options);
+ bool Start(CScheduler& scheduler, const Options& options);
void Stop();
void Interrupt();
bool GetNetworkActive() const { return fNetworkActive; };
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index a743f04dd1..6fabfcf0ad 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1260,6 +1260,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return false;
}
+ if (nServices & ((1 << 7) | (1 << 5))) {
+ if (GetTime() < 1533096000) {
+ // Immediately disconnect peers that use service bits 6 or 8 until August 1st, 2018
+ // These bits have been used as a flag to indicate that a node is running incompatible
+ // consensus rules instead of changing the network magic, so we're stuck disconnecting
+ // based on these service bits, at least for a while.
+ pfrom->fDisconnect = true;
+ return false;
+ }
+ }
+
if (nVersion < MIN_PEER_PROTO_VERSION)
{
// disconnect from peers older than this proto version
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index e82a3c1533..1e2f2302b9 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -762,7 +762,7 @@
<item>
<widget class="QLabel" name="fallbackFeeWarningLabel">
<property name="toolTip">
- <string>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until your have validated the complete chain.</string>
+ <string>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</string>
</property>
<property name="font">
<font>
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index 1e0d472b6a..231a715753 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -22,9 +22,9 @@
static const uint64_t GB_BYTES = 1000000000LL;
/* Minimum free space (in GB) needed for data directory */
-static const uint64_t BLOCK_CHAIN_SIZE = 120;
+static const uint64_t BLOCK_CHAIN_SIZE = 150;
/* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */
-static const uint64_t CHAIN_STATE_SIZE = 2;
+static const uint64_t CHAIN_STATE_SIZE = 3;
/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 4cd1048d11..821be8987e 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -2674,7 +2674,7 @@
</message>
<message>
<location line="+24"/>
- <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until your have validated the complete chain.</source>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
<translation type="unfinished"></translation>
</message>
<message>
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index cf75cdd744..d236b1de3f 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2789,10 +2789,6 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// selected to meet nFeeNeeded result in a transaction that
// requires less fee than the prior iteration.
- // TODO: The case where nSubtractFeeFromAmount > 0 remains
- // to be addressed because it requires returning the fee to
- // the payees and not the change output.
-
// If we have no change and a big enough excess fee, then
// try to construct transaction again only without picking
// new inputs. We now know we only need the smaller fee
@@ -2819,6 +2815,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
else if (!pick_new_inputs) {
// This shouldn't happen, we should have had enough excess
// fee to pay for the new output and still meet nFeeNeeded
+ // Or we should have just subtracted fee from recipients and
+ // nFeeNeeded should not have changed
strFailReason = _("Transaction fee and change calculation failed");
return false;
}
@@ -2835,6 +2833,12 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
}
}
+ // If subtracting fee from recipients, we now know what fee we
+ // need to subtract, we have no reason to reselect inputs
+ if (nSubtractFeeFromAmount > 0) {
+ pick_new_inputs = false;
+ }
+
// Include more fee and try again.
nFeeRet = nFeeNeeded;
continue;