diff options
34 files changed, 172 insertions, 145 deletions
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 509283a0b9..f43fc3037f 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -473,8 +473,8 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[ ]) BITCOIN_QT_CHECK(AC_CHECK_LIB([z] ,[main],,AC_MSG_WARN([zlib not found. Assuming qt has it built-in]))) - BITCOIN_QT_CHECK(AC_CHECK_LIB([png] ,[main],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in]))) - BITCOIN_QT_CHECK(AC_CHECK_LIB([jpeg] ,[main],,AC_MSG_WARN([libjpeg not found. Assuming qt has it built-in]))) + BITCOIN_QT_CHECK(AC_SEARCH_LIBS([png_error] ,[qtpng png],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in]))) + BITCOIN_QT_CHECK(AC_SEARCH_LIBS([jpeg_create_decompress] ,[qtjpeg jpeg],,AC_MSG_WARN([libjpeg not found. Assuming qt has it built-in]))) BITCOIN_QT_CHECK(AC_SEARCH_LIBS([pcre16_exec], [qtpcre pcre16],,AC_MSG_WARN([libpcre16 not found. Assuming qt has it built-in]))) BITCOIN_QT_CHECK(AC_SEARCH_LIBS([hb_ot_tags_from_script] ,[qtharfbuzzng harfbuzz],,AC_MSG_WARN([libharfbuzz not found. Assuming qt has it built-in or support is disabled]))) BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Core] ,[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXCore not found))) diff --git a/contrib/linearize/example-linearize.cfg b/contrib/linearize/example-linearize.cfg index cccdd79213..69f0e9247a 100644 --- a/contrib/linearize/example-linearize.cfg +++ b/contrib/linearize/example-linearize.cfg @@ -24,7 +24,7 @@ input=/home/example/.bitcoin/blocks output_file=/home/example/Downloads/bootstrap.dat hashlist=hashlist.txt -# Maxmimum size in bytes of out-of-order blocks cache in memory +# Maximum size in bytes of out-of-order blocks cache in memory out_of_order_cache_sz = 100000000 # Do we want the reverse the hash bytes coming from getblockhash? diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 4cf44385b8..088723ebd0 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -2,7 +2,7 @@ packages:=boost openssl libevent zeromq native_packages := native_ccache qt_native_packages = native_protobuf -qt_packages = qrencode protobuf +qt_packages = qrencode protobuf zlib qt_x86_64_linux_packages:=qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans qt_i686_linux_packages:=$(qt_x86_64_linux_packages) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 6e38d1ac6a..bbfdb766ed 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -4,7 +4,7 @@ $(package)_download_path=http://download.qt.io/official_releases/qt/5.7/$($(pack $(package)_suffix=opensource-src-$($(package)_version).tar.gz $(package)_file_name=qtbase-$($(package)_suffix) $(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410 -$(package)_dependencies=openssl +$(package)_dependencies=openssl zlib $(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib @@ -73,7 +73,7 @@ $(package)_config_opts += -prefix $(host_prefix) $(package)_config_opts += -qt-libpng $(package)_config_opts += -qt-libjpeg $(package)_config_opts += -qt-pcre -$(package)_config_opts += -qt-zlib +$(package)_config_opts += -system-zlib $(package)_config_opts += -reduce-exports $(package)_config_opts += -static $(package)_config_opts += -silent @@ -140,12 +140,13 @@ define $(package)_preprocess_cmds patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \ patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ - echo "QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ - echo "QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ - echo "QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ - sed -i.old "s|QMAKE_CFLAGS = |QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ - sed -i.old "s|QMAKE_LFLAGS = |QMAKE_LFLAGS = $($(package)_ldflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ - sed -i.old "s|QMAKE_CXXFLAGS = |QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf + echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ + echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ + echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ + sed -i.old "s|QMAKE_CFLAGS = |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_LFLAGS = |!host_build: QMAKE_LFLAGS = $($(package)_ldflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CXXFLAGS = |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf + endef define $(package)_config_cmds @@ -153,6 +154,8 @@ define $(package)_config_cmds export PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig && \ export PKG_CONFIG_PATH=$(host_prefix)/share/pkgconfig && \ ./configure $($(package)_config_opts) && \ + echo "host_build: QT_CONFIG ~= s/system-zlib/zlib" >> mkspecs/qconfig.pri && \ + echo "CONFIG += force_bootstrap" >> mkspecs/qconfig.pri && \ $(MAKE) sub-src-clean && \ cd ../qttranslations && ../qtbase/bin/qmake qttranslations.pro -o Makefile && \ cd translations && ../../qtbase/bin/qmake translations.pro -o Makefile && cd ../.. &&\ diff --git a/depends/packages/zlib.mk b/depends/packages/zlib.mk new file mode 100644 index 0000000000..7ff5d00bbd --- /dev/null +++ b/depends/packages/zlib.mk @@ -0,0 +1,25 @@ +package=zlib +$(package)_version=1.2.11 +$(package)_download_path=http://www.zlib.net +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_sha256_hash=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 + +define $(package)_set_vars +$(package)_build_opts= CC="$($(package)_cc)" +$(package)_build_opts+=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fPIC" +$(package)_build_opts+=AR="$($(package)_ar)" +$(package)_build_opts+=RANLIB="$($(package)_ranlib)" +endef + +define $(package)_config_cmds + ./configure --static --prefix=$(host_prefix) +endef + +define $(package)_build_cmds + $(MAKE) $($(package)_build_opts) libz.a +endef + +define $(package)_stage_cmds + $(MAKE) DESTDIR=$($(package)_staging_dir) install $($(package)_build_opts) +endef + diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf index f565fe3e75..ca70d30b15 100644 --- a/depends/patches/qt/mac-qmake.conf +++ b/depends/patches/qt/mac-qmake.conf @@ -14,10 +14,10 @@ QMAKE_MAC_SDK.macosx.Path = $${MAC_SDK_PATH} QMAKE_MAC_SDK.macosx.platform_name = macosx QMAKE_MAC_SDK.macosx.SDKVersion = $${MAC_SDK_VERSION} QMAKE_MAC_SDK.macosx.PlatformPath = /phony -QMAKE_CFLAGS += -target $${MAC_TARGET} -QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -QMAKE_LFLAGS += -target $${MAC_TARGET} -mlinker-version=$${MAC_LD64_VERSION} +!host_build: QMAKE_CFLAGS += -target $${MAC_TARGET} +!host_build: QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS +!host_build: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS +!host_build: QMAKE_LFLAGS += -target $${MAC_TARGET} -mlinker-version=$${MAC_LD64_VERSION} QMAKE_AR = $${CROSS_COMPILE}ar cq QMAKE_RANLIB=$${CROSS_COMPILE}ranlib QMAKE_LIBTOOL=$${CROSS_COMPILE}libtool diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 60a1a86fa8..9d155478e2 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -103,7 +103,7 @@ class PruneTest(BitcoinTestFramework): # Disconnect node 0 so it can mine a longer reorg chain without knowing about node 1's soon-to-be-stale chain # Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects # Stopping node 0 also clears its mempool, so it doesn't have node1's transactions to accidentally mine - stop_node(self.nodes[0],0) + self.stop_node(0) self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900) # Mine 24 blocks in node 1 for i in range(24): @@ -128,7 +128,7 @@ class PruneTest(BitcoinTestFramework): # This will cause Node 2 to do a reorg requiring 288 blocks of undo data to the reorg_test chain # Reboot node 1 to clear its mempool (hopefully make the invalidate faster) # Lower the block max size so we don't keep mining all our big mempool transactions (from disconnected blocks) - stop_node(self.nodes[1],1) + self.stop_node(1) self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) height = self.nodes[1].getblockcount() @@ -151,7 +151,7 @@ class PruneTest(BitcoinTestFramework): print("New best height", self.nodes[1].getblockcount()) # Reboot node1 to clear those giant tx's from mempool - stop_node(self.nodes[1],1) + self.stop_node(1) self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) print("Generating new longer chain of 300 more blocks") @@ -231,7 +231,7 @@ class PruneTest(BitcoinTestFramework): node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-debug=0"], timewait=900) assert_equal(node.getblockcount(), 995) assert_raises_message(JSONRPCException, "not in prune mode", node.pruneblockchain, 500) - stop_node(node, node_number) + self.stop_node(node_number) # now re-start in manual pruning mode node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-debug=0","-prune=1"], timewait=900) @@ -266,25 +266,21 @@ class PruneTest(BitcoinTestFramework): # mine 6 blocks so we are at height 1001 (i.e., above PruneAfterHeight) node.generate(6) + assert_equal(node.getblockchaininfo()["blocks"], 1001) - # negative and zero inputs should raise an exception - try: - node.pruneblockchain(-10) - raise AssertionError("pruneblockchain(-10) should have failed.") - except: - pass - - try: - node.pruneblockchain(0) - raise AssertionError("pruneblockchain(0) should have failed.") - except: - pass + # negative heights should raise an exception + assert_raises_message(JSONRPCException, "Negative", node.pruneblockchain, -10) # height=100 too low to prune first block file so this is a no-op prune(100) if not has_block(0): raise AssertionError("blk00000.dat is missing when should still be there") + # Does nothing + node.pruneblockchain(height(0)) + if not has_block(0): + raise AssertionError("blk00000.dat is missing when should still be there") + # height=500 should prune first file prune(500) if has_block(0): @@ -311,7 +307,7 @@ class PruneTest(BitcoinTestFramework): raise AssertionError("blk00003.dat is still there, should be pruned by now") # stop node, start back up with auto-prune at 550MB, make sure still runs - stop_node(node, node_number) + self.stop_node(node_number) self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-debug=0","-prune=550"], timewait=900) print("Success") @@ -320,7 +316,7 @@ class PruneTest(BitcoinTestFramework): # check that the pruning node's wallet is still in good shape print("Stop and start pruning node to trigger wallet rescan") try: - stop_node(self.nodes[2], 2) + self.stop_node(2) start_node(2, self.options.tmpdir, ["-debug=1","-prune=550"]) print("Success") except Exception as detail: @@ -333,7 +329,7 @@ class PruneTest(BitcoinTestFramework): nds = [self.nodes[0], self.nodes[5]] sync_blocks(nds, wait=5, timeout=300) try: - stop_node(self.nodes[5],5) #stop and start to trigger rescan + self.stop_node(5) #stop and start to trigger rescan start_node(5, self.options.tmpdir, ["-debug=1","-prune=550"]) print ("Success") except Exception as detail: @@ -353,8 +349,8 @@ class PruneTest(BitcoinTestFramework): # N0=N1=N2 **...*(995) # stop manual-pruning node with 995 blocks - stop_node(self.nodes[3],3) - stop_node(self.nodes[4],4) + self.stop_node(3) + self.stop_node(4) print("Check that we haven't started pruning yet because we're below PruneAfterHeight") self.test_height_min() diff --git a/src/addrman.cpp b/src/addrman.cpp index 662e931d25..ab84bf8e35 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -255,7 +255,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP int nId; CAddrInfo* pinfo = Find(addr, &nId); - // Do not set a penality for a source's self-announcement + // Do not set a penalty for a source's self-announcement if (addr == source) { nTimePenalty = 0; } diff --git a/src/base58.h b/src/base58.h index cccebc9e0e..3998283bb1 100644 --- a/src/base58.h +++ b/src/base58.h @@ -147,7 +147,7 @@ public: K GetKey() { K ret; if (vchData.size() == Size) { - //if base58 encouded data not holds a ext key, return a !IsValid() key + // If base58 encoded data does not hold an ext key, return a !IsValid() key ret.Decode(&vchData[0]); } return ret; diff --git a/src/bench/perf.cpp b/src/bench/perf.cpp index 1f43e5d3ac..a549ec29ea 100644 --- a/src/bench/perf.cpp +++ b/src/bench/perf.cpp @@ -6,7 +6,7 @@ #if defined(__i386__) || defined(__x86_64__) -/* These architectures support quering the cycle counter +/* These architectures support querying the cycle counter * from user space, no need for any syscall overhead. */ void perf_init(void) { } diff --git a/src/blockencodings.h b/src/blockencodings.h index 281db9fe01..5a1d80d421 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -99,7 +99,7 @@ public: } }; -// Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownlaodedBlock +// Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock struct PrefilledTransaction { // Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs, // as a proper transaction-in-block-index in PartiallyDownloadedBlock diff --git a/src/consensus/params.h b/src/consensus/params.h index 3f98938f7e..6240e82857 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -47,7 +47,7 @@ struct Params { /** Block height at which BIP66 becomes active */ int BIP66Height; /** - * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period, + * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. * Examples: 1916 for 95%, 1512 for testchains. */ diff --git a/src/cuckoocache.h b/src/cuckoocache.h index efd6a820b5..ff47e9776b 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -257,7 +257,7 @@ private: * * First, epoch_check decrements and checks the cheap heuristic, and then does * a more expensive scan if the cheap heuristic runs out. If the expensive - * scan suceeds, the epochs are aged and old elements are allow_erased. The + * scan succeeds, the epochs are aged and old elements are allow_erased. The * cheap heuristic is reset to retrigger after the worst case growth of the * current epoch's elements would exceed the epoch_size. */ @@ -395,7 +395,7 @@ public: * 1) On first iteration, last_loc == invalid(), find returns last, so * last_loc defaults to locs[0]. * 2) On further iterations, where last_loc == locs[k], last_loc will - * go to locs[k+1 % 8], i.e., next of the 8 indicies wrapping around + * go to locs[k+1 % 8], i.e., next of the 8 indices wrapping around * to 0 if needed. * * This prevents moving the element we just put in. diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 93beda09a4..daac7a0f1a 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -25,7 +25,7 @@ static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\""; /** Simple one-shot callback timer to be used by the RPC mechanism to e.g. - * re-lock the wellet. + * re-lock the wallet. */ class HTTPRPCTimer : public RPCTimerBase { diff --git a/src/init.cpp b/src/init.cpp index 453fd833a3..d7d60b0fbc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1550,7 +1550,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } if (chainparams.GetConsensus().vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) { - // Only advertize witness capabilities if they have a reasonable start time. + // Only advertise witness capabilities if they have a reasonable start time. // This allows us to have the code merged without a defined softfork, by setting its // end time to 0. // Note that setting NODE_WITNESS is never required: the only downside from not diff --git a/src/net.cpp b/src/net.cpp index 1563a0963f..df88b12c76 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -342,8 +342,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo CNode* pnode = FindNode((CService)addrConnect); if (pnode) { - pnode->AddRef(); - return pnode; + LogPrintf("Failed to open new connection, already connected\n"); + return NULL; } } @@ -369,18 +369,16 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo // In that case, drop the connection that was just created, and return the existing CNode instead. // Also store the name we used to connect in that CNode, so that future FindNode() calls to that // name catch this early. + LOCK(cs_vNodes); CNode* pnode = FindNode((CService)addrConnect); if (pnode) { - pnode->AddRef(); - { - LOCK(cs_vNodes); - if (pnode->addrName.empty()) { - pnode->addrName = std::string(pszDest); - } + if (pnode->addrName.empty()) { + pnode->addrName = std::string(pszDest); } CloseSocket(hSocket); - return pnode; + LogPrintf("Failed to open new connection, already connected\n"); + return NULL; } } @@ -393,11 +391,6 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices); pnode->nTimeConnected = GetSystemTimeInSeconds(); pnode->AddRef(); - GetNodeSignals().InitializeNode(pnode, *this); - { - LOCK(cs_vNodes); - vNodes.push_back(pnode); - } return pnode; } else if (!proxyConnectionFailed) { @@ -1840,6 +1833,12 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai if (fAddnode) pnode->fAddnode = true; + { + LOCK(cs_vNodes); + vNodes.push_back(pnode); + } + GetNodeSignals().InitializeNode(pnode, *this); + return true; } @@ -2371,26 +2370,9 @@ void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats) } } -bool CConnman::DisconnectAddress(const CNetAddr& netAddr) -{ - if (CNode* pnode = FindNode(netAddr)) { - pnode->fDisconnect = true; - return true; - } - return false; -} - -bool CConnman::DisconnectSubnet(const CSubNet& subNet) -{ - if (CNode* pnode = FindNode(subNet)) { - pnode->fDisconnect = true; - return true; - } - return false; -} - bool CConnman::DisconnectNode(const std::string& strNode) { + LOCK(cs_vNodes); if (CNode* pnode = FindNode(strNode)) { pnode->fDisconnect = true; return true; @@ -2409,16 +2391,6 @@ bool CConnman::DisconnectNode(NodeId id) return false; } -void CConnman::RelayTransaction(const CTransaction& tx) -{ - CInv inv(MSG_TX, tx.GetHash()); - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - pnode->PushInventory(inv); - } -} - void CConnman::RecordBytesRecv(uint64_t bytes) { LOCK(cs_totalBytesRecv); @@ -243,8 +243,6 @@ public: post(); }; - void RelayTransaction(const CTransaction& tx); - // Addrman functions size_t GetAddressCount() const; void SetServices(const CService &addr, ServiceFlags nServices); @@ -286,10 +284,8 @@ public: size_t GetNodeCount(NumConnections num); void GetNodeStats(std::vector<CNodeStats>& vstats); - bool DisconnectAddress(const CNetAddr& addr); bool DisconnectNode(const std::string& node); bool DisconnectNode(NodeId id); - bool DisconnectSubnet(const CSubNet& subnet); unsigned int GetSendBufferSize() const; diff --git a/src/netaddress.h b/src/netaddress.h index bc430dd823..a85c2b7452 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -49,7 +49,7 @@ class CNetAddr bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) - bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15) + bool IsRFC2544() const; // IPv4 inter-network communications (192.18.0.0/15) bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10) bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 00a915dd8d..4b34e73eb7 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -64,7 +64,7 @@ public: } if (sortColumn >= 0) - // sort cachedBanlist (use stable sort to prevent rows jumping around unneceesarily) + // sort cachedBanlist (use stable sort to prevent rows jumping around unnecessarily) qStableSort(cachedBanlist.begin(), cachedBanlist.end(), BannedNodeLessThan(sortColumn, sortOrder)); } diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 37ee522d54..9d46280a37 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -21,10 +21,10 @@ // // When startup is finished and the main window is // shown, a signal is sent to slot uiReady(), which -// emits a receivedURL() signal for any payment +// emits a receivedURI() signal for any payment // requests that happened during startup. // -// After startup, receivedURL() happens as usual. +// After startup, receivedURI() happens as usual. // // This class has one more feature: a static // method that finds URIs passed in the command line diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 1e2842df73..1c0ed663c1 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -608,7 +608,7 @@ void SendCoinsDialog::updateGlobalFeeVariables() // set nMinimumTotalFee to 0 to not accidentally pay a custom fee CoinControlDialog::coinControl->nMinimumTotalFee = 0; - // show the estimated reuquired time for confirmation + // show the estimated required time for confirmation ui->confirmationTargetLabel->setText(GUIUtil::formatDurationStr(nConfirmTarget * Params().GetConsensus().nPowTargetSpacing) + " / " + tr("%n block(s)", "", nConfirmTarget)); } else diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index cbdedbf68b..a9d9b6887e 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -47,14 +47,15 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * // // Credit // - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) { + const CTxOut& txout = wtx.tx->vout[i]; isminetype mine = wallet->IsMine(txout); if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; - sub.idx = parts.size(); // sequence number + sub.idx = i; // vout index sub.credit = txout.nValue; sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) @@ -118,7 +119,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * { const CTxOut& txout = wtx.tx->vout[nOut]; TransactionRecord sub(hash, nTime); - sub.idx = parts.size(); + sub.idx = nOut; sub.involvesWatchAddress = involvesWatchAddress; if(wallet->IsMine(txout)) diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 70efe27990..7ab4125284 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -39,7 +39,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : QString version = tr(PACKAGE_NAME) + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()); /* On x86 add a bit specifier to the version so that users can distinguish between - * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious. + * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambiguous. */ #if defined(__x86_64__) version += " " + tr("(%1-bit)").arg(64); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 27b9963a10..f590db5efa 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -10,6 +10,7 @@ #include "net.h" #include "net_processing.h" #include "netbase.h" +#include "policy/policy.h" #include "protocol.h" #include "sync.h" #include "timedata.h" @@ -150,7 +151,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) obj.push_back(Pair("pingwait", stats.dPingWait)); obj.push_back(Pair("version", stats.nVersion)); // Use the sanitized form of subver here, to avoid tricksy remote peers from - // corrupting or modifiying the JSON output by putting special characters in + // corrupting or modifying the JSON output by putting special characters in // their ver message. obj.push_back(Pair("subver", stats.cleanSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); @@ -417,6 +418,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) " ,...\n" " ],\n" " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" + " \"incrementalfee\": x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n" " \"localaddresses\": [ (array) list of local addresses\n" " {\n" " \"address\": \"xxxx\", (string) network address\n" @@ -447,6 +449,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) } obj.push_back(Pair("networks", GetNetworksInfo())); obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); + obj.push_back(Pair("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()))); UniValue localAddresses(UniValue::VARR); { LOCK(cs_mapLocalHost); diff --git a/src/script/script.cpp b/src/script/script.cpp index 828ce1a056..9f4741b1cd 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -129,7 +129,7 @@ const char* GetOpName(opcodetype opcode) case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG"; case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY"; - // expanson + // expansion case OP_NOP1 : return "OP_NOP1"; case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY"; case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY"; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 2f74f57d00..f856d8a91a 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -9,6 +9,7 @@ #include "consensus/validation.h" #include "validation.h" #include "miner.h" +#include "policy/policy.h" #include "pubkey.h" #include "script/standard.h" #include "txmempool.h" @@ -24,6 +25,8 @@ BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) +static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); + static struct { unsigned char extranonce; @@ -112,7 +115,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx); BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx); - // Test that a package below the min relay fee doesn't get included + // Test that a package below the block min tx fee doesn't get included tx.vin[0].prevout.hash = hashHighFeeTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee uint256 hashFreeTx = tx.GetHash(); @@ -120,8 +123,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); // Calculate a fee on child transaction that will put the package just - // below the min relay fee (assuming 1 child tx of the same size). - CAmount feeToUse = minRelayTxFee.GetFee(2*freeTxSize) - 1; + // below the block min tx fee (assuming 1 child tx of the same size). + CAmount feeToUse = blockMinFeeRate.GetFee(2*freeTxSize) - 1; tx.vin[0].prevout.hash = hashFreeTx; tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; @@ -158,7 +161,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, // This tx can't be mined by itself tx.vin[0].prevout.hash = hashFreeTx2; tx.vout.resize(1); - feeToUse = minRelayTxFee.GetFee(freeTxSize); + feeToUse = blockMinFeeRate.GetFee(freeTxSize); tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; uint256 hashLowFeeTx2 = tx.GetHash(); mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 2d54668eaf..9661a66514 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(sizes) BOOST_AUTO_TEST_CASE(floats_conversion) { - // Choose values that map unambigiously to binary floating point to avoid + // Choose values that map unambiguously to binary floating point to avoid // rounding issues at the compiler side. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x00000000), 0.0F); BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f000000), 0.5F); @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(floats_conversion) BOOST_AUTO_TEST_CASE(doubles_conversion) { - // Choose values that map unambigiously to binary floating point to avoid + // Choose values that map unambiguously to binary floating point to avoid // rounding issues at the compiler side. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x0000000000000000ULL), 0.0); BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3fe0000000000000ULL), 0.5); diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 5571b7de44..c49c5d9eb2 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -372,7 +372,7 @@ private: struct event *reconnect_ev; float reconnect_timeout; CService service; - /** Cooie for SAFECOOKIE auth */ + /** Cookie for SAFECOOKIE auth */ std::vector<uint8_t> cookie; /** ClientNonce for SAFECOOKIE auth */ std::vector<uint8_t> clientNonce; diff --git a/src/txmempool.h b/src/txmempool.h index f842a07dd6..db1a02455f 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -355,7 +355,7 @@ enum class MemPoolRemovalReason { * Transactions are added when they are seen on the network (or created by the * local node), but not all transactions seen are added to the pool. For * example, the following new transactions will not be added to the mempool: - * - a transaction which doesn't make the mimimum fee requirements. + * - a transaction which doesn't meet the minimum fee requirements. * - a new transaction that double-spends an input of a transaction already in * the pool where the new transaction does not meet the Replace-By-Fee * requirements as defined in BIP 125. diff --git a/src/utiltime.cpp b/src/utiltime.cpp index 87a25866e9..c7b3e4f168 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -63,7 +63,7 @@ void MilliSleep(int64_t n) { /** - * Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50 + * Boost's sleep_for was uninterruptible when backed by nanosleep from 1.50 * until fixed in 1.52. Use the deprecated sleep method for the broken case. * See: https://svn.boost.org/trac/boost/ticket/7238 */ diff --git a/src/validation.cpp b/src/validation.cpp index 5a14e7475e..fe8f8365be 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -930,14 +930,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Finally in addition to paying more fees than the conflicts the // new transaction must pay for its own bandwidth. CAmount nDeltaFees = nModifiedFees - nConflictingFees; - if (nDeltaFees < ::minRelayTxFee.GetFee(nSize)) + if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize)) { return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient fee", false, strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s", hash.ToString(), FormatMoney(nDeltaFees), - FormatMoney(::minRelayTxFee.GetFee(nSize)))); + FormatMoney(::incrementalRelayFee.GetFee(nSize)))); } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 87bf3ecbb0..bfc738afad 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2682,8 +2682,8 @@ UniValue bumpfee(const JSONRPCRequest& request) "By default, the new fee will be calculated automatically using estimatefee.\n" "The user can specify a confirmation target for estimatefee.\n" "Alternatively, the user can specify totalFee, or use RPC setpaytxfee to set a higher fee rate.\n" - "At a minimum, the new fee rate must be high enough to pay a new relay fee (relay fee amount returned\n" - "by getnetworkinfo RPC) and to enter the node's mempool.\n" + "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n" + "returned by getnetworkinfo) to enter the node's mempool.\n" "\nArguments:\n" "1. txid (string, required) The txid to be bumped\n" "2. options (object, optional)\n" @@ -2704,8 +2704,8 @@ UniValue bumpfee(const JSONRPCRequest& request) "\nResult:\n" "{\n" " \"txid\": \"value\", (string) The id of the new transaction\n" - " \"oldfee\": n, (numeric) Fee of the replaced transaction\n" - " \"fee\": n, (numeric) Fee of the new transaction\n" + " \"origfee\": n, (numeric) Fee of the replaced transaction\n" + " \"fee\": n, (numeric) Fee of the new transaction\n" "}\n" "\nExamples:\n" "\nBump the fee, get the new transaction\'s txid\n" + @@ -2769,6 +2769,10 @@ UniValue bumpfee(const JSONRPCRequest& request) throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not have a change output"); } + // signature sizes can vary by a byte, so add 1 for each input when calculating the new fee + int64_t txSize = GetVirtualTransactionSize(*(wtx.tx)); + const int64_t maxNewTxSize = txSize + wtx.tx->vin.size(); + // optional parameters bool specifiedConfirmTarget = false; int newConfirmTarget = nTxConfirmTarget; @@ -2794,10 +2798,11 @@ UniValue bumpfee(const JSONRPCRequest& request) } } else if (options.exists("totalFee")) { totalFee = options["totalFee"].get_int64(); - if (totalFee <= 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be <= 0)"); - } else if (totalFee > maxTxFee) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be higher than maxTxFee)"); + CAmount requiredFee = CWallet::GetRequiredFee(maxNewTxSize); + if (totalFee < requiredFee ) { + throw JSONRPCError(RPC_INVALID_PARAMETER, + strprintf("Insufficient totalFee (cannot be less than required fee %s)", + FormatMoney(requiredFee))); } } @@ -2806,42 +2811,53 @@ UniValue bumpfee(const JSONRPCRequest& request) } } - // signature sizes can vary by a byte, so add 1 for each input when calculating the new fee - int64_t txSize = GetVirtualTransactionSize(*(wtx.tx)); - const int64_t maxNewTxSize = txSize + wtx.tx->vin.size(); - // calculate the old fee and fee-rate CAmount nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); CFeeRate nOldFeeRate(nOldFee, txSize); CAmount nNewFee; CFeeRate nNewFeeRate; + // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to + // future proof against changes to network wide policy for incremental relay + // fee that our node may not be aware of. + CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE); + if (::incrementalRelayFee > walletIncrementalRelayFee) { + walletIncrementalRelayFee = ::incrementalRelayFee; + } if (totalFee > 0) { - CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + minRelayTxFee.GetFee(maxNewTxSize); + CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + ::incrementalRelayFee.GetFee(maxNewTxSize); if (totalFee < minTotalFee) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid totalFee, must be at least %s (oldFee %s + relayFee %s)", FormatMoney(minTotalFee), nOldFeeRate.GetFee(maxNewTxSize), minRelayTxFee.GetFee(maxNewTxSize))); + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)", + FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize)))); } nNewFee = totalFee; nNewFeeRate = CFeeRate(totalFee, maxNewTxSize); } else { - // use the user-defined payTxFee if possible, otherwise use smartfee / fallbackfee - if (!specifiedConfirmTarget && payTxFee.GetFeePerK() != 0) { - nNewFeeRate = payTxFee; - } else { - nNewFeeRate = mempool.estimateSmartFee(newConfirmTarget); + // if user specified a confirm target then don't consider any global payTxFee + if (specifiedConfirmTarget) { + nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, CAmount(0)); } - if (nNewFeeRate.GetFeePerK() == 0) { - nNewFeeRate = CWallet::fallbackFee; + // otherwise use the regular wallet logic to select payTxFee or default confirm target + else { + nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool); } - // new fee rate must be at least old rate + minimum relay rate - if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + ::minRelayTxFee.GetFeePerK()) { - nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + ::minRelayTxFee.GetFeePerK()); - } + nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); - nNewFee = nNewFeeRate.GetFee(maxNewTxSize); + // New fee rate must be at least old rate + minimum incremental relay rate + if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + walletIncrementalRelayFee.GetFeePerK()) { + nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + walletIncrementalRelayFee.GetFeePerK()); + nNewFee = nNewFeeRate.GetFee(maxNewTxSize); + } } + // Check that in all cases the new fee doesn't violate maxTxFee + if (nNewFee > maxTxFee) { + throw JSONRPCError(RPC_MISC_ERROR, + strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)", + FormatMoney(nNewFee), FormatMoney(maxTxFee))); + } + // check that fee rate is higher than mempool's minimum fee // (no point in bumping fee if we know that the new tx won't be accepted to the mempool) // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, @@ -2864,7 +2880,7 @@ UniValue bumpfee(const JSONRPCRequest& request) // If the output would become dust, discard it (converting the dust to fee) poutput->nValue -= nDelta; - if (poutput->nValue <= poutput->GetDustThreshold(::minRelayTxFee)) { + if (poutput->nValue <= poutput->GetDustThreshold(::dustRelayFee)) { LogPrint("rpc", "Bumping fee and discarding dust output\n"); nNewFee += poutput->nValue; tx.vout.erase(tx.vout.begin() + nOutput); @@ -2913,7 +2929,7 @@ UniValue bumpfee(const JSONRPCRequest& request) UniValue result(UniValue::VOBJ); result.push_back(Pair("txid", wtxBumped.GetHash().GetHex())); - result.push_back(Pair("oldfee", ValueFromAmount(nOldFee))); + result.push_back(Pair("origfee", ValueFromAmount(nOldFee))); result.push_back(Pair("fee", ValueFromAmount(nNewFee))); return result; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b4715622cf..9a5f35b6e3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2576,7 +2576,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt // BIP125 defines opt-in RBF as any nSequence < maxint-1, so // we use the highest possible value in that range (maxint-2) // to avoid conflicting with other possible uses of nSequence, - // and in the spirit of "smallest posible change from prior + // and in the spirit of "smallest possible change from prior // behavior." for (const auto& coin : setCoins) txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), @@ -2802,8 +2802,13 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) { - // payTxFee is user-set "I want to pay this much" - CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); + // payTxFee is the user-set global for desired feerate + return GetMinimumFee(nTxBytes, nConfirmTarget, pool, payTxFee.GetFee(nTxBytes)); +} + +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee) +{ + CAmount nFeeNeeded = targetFee; // User didn't set: use -txconfirmtarget to estimate... if (nFeeNeeded == 0) { int estimateFoundTarget = nConfirmTarget; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a7fc05b62d..200ec0cba2 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -48,6 +48,8 @@ static const CAmount DEFAULT_TRANSACTION_FEE = 0; static const CAmount DEFAULT_FALLBACK_FEE = 20000; //! -mintxfee default static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000; +//! minimum recommended increment for BIP 125 replacement txs +static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000; //! target minimum change amount static const CAmount MIN_CHANGE = CENT; //! final minimum change amount after paying for fees @@ -803,6 +805,11 @@ public: */ static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); /** + * Estimate the minimum fee considering required fee and targetFee or if 0 + * then fee estimation for nConfirmTarget + */ + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee); + /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee */ |