From 91a25d1e711bfc0617027eee18b9777ff368d6b9 Mon Sep 17 00:00:00 2001
From: John Newbery <john@johnnewbery.com>
Date: Tue, 2 Apr 2019 17:03:37 -0400
Subject: [PATCH] [build] Add several util units

Adds the following util units and adds them to libbitcoin_util:

- `util/url.cpp` takes `urlDecode` from `httpserver.cpp`
- `util/error.cpp` takes `TransactionErrorString` from
  `node/transaction.cpp` and `AmountHighWarn` and `AmountErrMsg` from
  `ui_interface.cpp`
- `util/fees.cpp` takes `StringForFeeReason` and `FeeModeFromString` from `policy/fees.cpp`
- `util/rbf.cpp` takes `SignalsOptInRBF` from `policy/rbf.cpp`
- 'util/validation.cpp` takes `FormatStateMessage` and `strMessageMagic` from 'validation.cpp`
---
 src/Makefile.am                         | 10 ++++++
 src/bitcoin-tx.cpp                      |  1 +
 src/httpserver.cpp                      | 12 -------
 src/httpserver.h                        |  2 --
 src/init.cpp                            |  1 +
 src/miner.cpp                           |  1 +
 src/net_processing.cpp                  |  1 +
 src/node/transaction.cpp                | 27 +---------------
 src/node/transaction.h                  | 15 +--------
 src/policy/fees.cpp                     | 34 -------------------
 src/policy/fees.h                       |  4 ---
 src/policy/policy.cpp                   |  1 -
 src/policy/rbf.cpp                      | 11 +------
 src/policy/rbf.h                        |  6 ----
 src/qt/signverifymessagedialog.cpp      |  2 +-
 src/rpc/blockchain.cpp                  |  1 +
 src/rpc/mining.cpp                      |  2 ++
 src/rpc/misc.cpp                        |  1 +
 src/rpc/rawtransaction_util.cpp         |  2 +-
 src/test/test_bitcoin.cpp               |  1 +
 src/ui_interface.cpp                    | 10 ------
 src/ui_interface.h                      |  4 ---
 src/util/error.cpp                      | 43 +++++++++++++++++++++++++
 src/util/error.h                        | 38 ++++++++++++++++++++++
 src/util/fees.cpp                       | 42 ++++++++++++++++++++++++
 src/util/fees.h                         | 16 +++++++++
 src/util/rbf.cpp                        | 17 ++++++++++
 src/util/rbf.h                          | 18 +++++++++++
 src/util/url.cpp                        | 21 ++++++++++++
 src/util/url.h                          | 12 +++++++
 src/util/validation.cpp                 | 20 ++++++++++++
 src/util/validation.h                   | 18 +++++++++++
 src/validation.cpp                      | 13 ++------
 src/validation.h                        |  4 ---
 src/wallet/feebumper.cpp                |  2 ++
 src/wallet/init.cpp                     |  1 +
 src/wallet/rpcwallet.cpp                |  4 ++-
 src/wallet/wallet.cpp                   |  4 +++
 test/lint/lint-circular-dependencies.sh |  3 +-
 39 files changed, 282 insertions(+), 143 deletions(-)
 create mode 100644 src/util/error.cpp
 create mode 100644 src/util/error.h
 create mode 100644 src/util/fees.cpp
 create mode 100644 src/util/fees.h
 create mode 100644 src/util/rbf.cpp
 create mode 100644 src/util/rbf.h
 create mode 100644 src/util/url.cpp
 create mode 100644 src/util/url.h
 create mode 100644 src/util/validation.cpp
 create mode 100644 src/util/validation.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 0a4108843..21fd365d3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -203,10 +203,15 @@ BITCOIN_CORE_H = \
   undo.h \
   util/bip32.h \
   util/bytevectorhash.h \
+  util/error.h \
+  util/fees.h \
   util/system.h \
   util/memory.h \
   util/moneystr.h \
+  util/rbf.h \
   util/time.h \
+  util/url.h \
+  util/validation.h \
   validation.h \
   validationinterface.h \
   versionbits.h \
@@ -471,10 +476,15 @@ libbitcoin_util_a_SOURCES = \
   threadinterrupt.cpp \
   util/bip32.cpp \
   util/bytevectorhash.cpp \
+  util/error.cpp \
+  util/fees.cpp \
   util/system.cpp \
   util/moneystr.cpp \
+  util/rbf.cpp \
   util/strencodings.cpp \
   util/time.cpp \
+  util/url.cpp \
+  util/validation.cpp \
   $(BITCOIN_CORE_H)
 
 if GLIBC_BACK_COMPAT
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 4be89aab6..7f41ea7ae 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -18,6 +18,7 @@
 #include <script/script.h>
 #include <script/sign.h>
 #include <univalue.h>
+#include <util/rbf.h>
 #include <util/system.h>
 #include <util/moneystr.h>
 #include <util/strencodings.h>
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index b9ca037c9..5d9c3d2c1 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -655,15 +655,3 @@ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
         pathHandlers.erase(i);
     }
 }
-
-std::string urlDecode(const std::string &urlEncoded) {
-    std::string res;
-    if (!urlEncoded.empty()) {
-        char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
-        if (decoded) {
-            res = std::string(decoded);
-            free(decoded);
-        }
-    }
-    return res;
-}
diff --git a/src/httpserver.h b/src/httpserver.h
index 63f96734f..7943f0094 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -148,6 +148,4 @@ private:
     struct event* ev;
 };
 
-std::string urlDecode(const std::string &urlEncoded);
-
 #endif // BITCOIN_HTTPSERVER_H
diff --git a/src/init.cpp b/src/init.cpp
index 652b99474..f5347bb8f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -47,6 +47,7 @@
 #include <ui_interface.h>
 #include <util/system.h>
 #include <util/moneystr.h>
+#include <util/validation.h>
 #include <validationinterface.h>
 #include <warnings.h>
 #include <walletinitinterface.h>
diff --git a/src/miner.cpp b/src/miner.cpp
index 80a2f8f01..6a88e8321 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -23,6 +23,7 @@
 #include <timedata.h>
 #include <util/moneystr.h>
 #include <util/system.h>
+#include <util/validation.h>
 #include <validationinterface.h>
 
 #include <algorithm>
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 044fcc90c..74e33189d 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -29,6 +29,7 @@
 #include <util/system.h>
 #include <util/moneystr.h>
 #include <util/strencodings.h>
+#include <util/validation.h>
 
 #include <memory>
 
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 7b9b4310e..5ffb15ed3 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -6,38 +6,13 @@
 #include <consensus/validation.h>
 #include <net.h>
 #include <txmempool.h>
+#include <util/validation.h>
 #include <validation.h>
 #include <validationinterface.h>
 #include <node/transaction.h>
 
 #include <future>
 
-std::string TransactionErrorString(const TransactionError err)
-{
-    switch (err) {
-        case TransactionError::OK:
-            return "No error";
-        case TransactionError::MISSING_INPUTS:
-            return "Missing inputs";
-        case TransactionError::ALREADY_IN_CHAIN:
-            return "Transaction already in block chain";
-        case TransactionError::P2P_DISABLED:
-            return "Peer-to-peer functionality missing or disabled";
-        case TransactionError::MEMPOOL_REJECTED:
-            return "Transaction rejected by AcceptToMemoryPool";
-        case TransactionError::MEMPOOL_ERROR:
-            return "AcceptToMemoryPool failed";
-        case TransactionError::INVALID_PSBT:
-            return "PSBT is not sane";
-        case TransactionError::PSBT_MISMATCH:
-            return "PSBTs not compatible (different transactions)";
-        case TransactionError::SIGHASH_MISMATCH:
-            return "Specified sighash value does not match existing value";
-        // no default case, so the compiler can warn about missing cases
-    }
-    assert(false);
-}
-
 TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee)
 {
     std::promise<void> promise;
diff --git a/src/node/transaction.h b/src/node/transaction.h
index 3457ececa..51033f94e 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -8,20 +8,7 @@
 #include <attributes.h>
 #include <primitives/transaction.h>
 #include <uint256.h>
-
-enum class TransactionError {
-    OK, //!< No error
-    MISSING_INPUTS,
-    ALREADY_IN_CHAIN,
-    P2P_DISABLED,
-    MEMPOOL_REJECTED,
-    MEMPOOL_ERROR,
-    INVALID_PSBT,
-    PSBT_MISMATCH,
-    SIGHASH_MISMATCH,
-};
-
-std::string TransactionErrorString(const TransactionError error);
+#include <util/error.h>
 
 /**
  * Broadcast a transaction
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index c49b9fa36..524afd014 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -27,40 +27,6 @@ std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
     return horizon_string->second;
 }
 
-std::string StringForFeeReason(FeeReason reason) {
-    static const std::map<FeeReason, std::string> fee_reason_strings = {
-        {FeeReason::NONE, "None"},
-        {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
-        {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
-        {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
-        {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
-        {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
-        {FeeReason::PAYTXFEE, "PayTxFee set"},
-        {FeeReason::FALLBACK, "Fallback fee"},
-        {FeeReason::REQUIRED, "Minimum Required Fee"},
-        {FeeReason::MAXTXFEE, "MaxTxFee limit"}
-    };
-    auto reason_string = fee_reason_strings.find(reason);
-
-    if (reason_string == fee_reason_strings.end()) return "Unknown";
-
-    return reason_string->second;
-}
-
-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
-    static const std::map<std::string, FeeEstimateMode> fee_modes = {
-        {"UNSET", FeeEstimateMode::UNSET},
-        {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
-        {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
-    };
-    auto mode = fee_modes.find(mode_string);
-
-    if (mode == fee_modes.end()) return false;
-
-    fee_estimate_mode = mode->second;
-    return true;
-}
-
 /**
  * We will instantiate an instance of this class to track transactions that were
  * included in a block. We will lump transactions into a bucket according to their
diff --git a/src/policy/fees.h b/src/policy/fees.h
index c8472a12f..6e61f7617 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -46,8 +46,6 @@ enum class FeeReason {
     MAXTXFEE,
 };
 
-std::string StringForFeeReason(FeeReason reason);
-
 /* Used to determine type of fee estimation requested */
 enum class FeeEstimateMode {
     UNSET,        //!< Use default settings based on other criteria
@@ -55,8 +53,6 @@ enum class FeeEstimateMode {
     CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
 };
 
-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
-
 /* Used to return detailed information about a feerate bucket */
 struct EstimatorBucket
 {
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index f1e6aadb5..44c23661f 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -8,7 +8,6 @@
 #include <policy/policy.h>
 
 #include <consensus/validation.h>
-#include <validation.h>
 #include <coins.h>
 #include <policy/settings.h>
 #include <tinyformat.h>
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index c73a97fd7..b4b8341d7 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -3,16 +3,7 @@
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <policy/rbf.h>
-
-bool SignalsOptInRBF(const CTransaction &tx)
-{
-    for (const CTxIn &txin : tx.vin) {
-        if (txin.nSequence <= MAX_BIP125_RBF_SEQUENCE) {
-            return true;
-        }
-    }
-    return false;
-}
+#include <util/rbf.h>
 
 RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
 {
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index a4f877731..0707b0044 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -7,18 +7,12 @@
 
 #include <txmempool.h>
 
-static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
-
 enum class RBFTransactionState {
     UNKNOWN,
     REPLACEABLE_BIP125,
     FINAL
 };
 
-// Check whether the sequence numbers on this transaction are signaling
-// opt-in to replace-by-fee, according to BIP 125
-bool SignalsOptInRBF(const CTransaction &tx);
-
 // Determine whether an in-mempool transaction is signaling opt-in to RBF
 // according to BIP 125
 // This involves checking sequence numbers of the transaction, as well
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index d37a78fa8..64cc85d62 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -11,7 +11,7 @@
 #include <qt/walletmodel.h>
 
 #include <key_io.h>
-#include <validation.h> // For strMessageMagic
+#include <util/validation.h> // For strMessageMagic
 #include <wallet/wallet.h>
 
 #include <string>
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d35f458b2..3db24080d 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -29,6 +29,7 @@
 #include <txmempool.h>
 #include <util/strencodings.h>
 #include <util/system.h>
+#include <util/validation.h>
 #include <validation.h>
 #include <validationinterface.h>
 #include <versionbitsinfo.h>
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 480d61023..c636102b2 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -21,8 +21,10 @@
 #include <rpc/util.h>
 #include <shutdown.h>
 #include <txmempool.h>
+#include <util/fees.h>
 #include <util/strencodings.h>
 #include <util/system.h>
+#include <util/validation.h>
 #include <validation.h>
 #include <validationinterface.h>
 #include <versionbitsinfo.h>
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 0a97f8029..f22184734 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -20,6 +20,7 @@
 #include <timedata.h>
 #include <util/system.h>
 #include <util/strencodings.h>
+#include <util/validation.h>
 #include <warnings.h>
 
 #include <stdint.h>
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 8b2ab8fa9..728fc62e2 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -11,12 +11,12 @@
 #include <key_io.h>
 #include <keystore.h>
 #include <policy/policy.h>
-#include <policy/rbf.h>
 #include <primitives/transaction.h>
 #include <rpc/protocol.h>
 #include <rpc/util.h>
 #include <tinyformat.h>
 #include <univalue.h>
+#include <util/rbf.h>
 #include <util/strencodings.h>
 
 CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf)
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index cdfd4db58..b72f15664 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -19,6 +19,7 @@
 #include <script/sigcache.h>
 #include <streams.h>
 #include <ui_interface.h>
+#include <util/validation.h>
 #include <validation.h>
 
 const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp
index 16ab24686..c084c4e0e 100644
--- a/src/ui_interface.cpp
+++ b/src/ui_interface.cpp
@@ -69,13 +69,3 @@ void InitWarning(const std::string& str)
 {
     uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
 }
-
-std::string AmountHighWarn(const std::string& optname)
-{
-    return strprintf(_("%s is set very high!"), optname);
-}
-
-std::string AmountErrMsg(const char* const optname, const std::string& strValue)
-{
-    return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
-}
diff --git a/src/ui_interface.h b/src/ui_interface.h
index f1aebce3b..60d85bc14 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -129,10 +129,6 @@ void InitWarning(const std::string& str);
 /** Show error message **/
 bool InitError(const std::string& str);
 
-std::string AmountHighWarn(const std::string& optname);
-
-std::string AmountErrMsg(const char* const optname, const std::string& strValue);
-
 extern CClientUIInterface uiInterface;
 
 #endif // BITCOIN_UI_INTERFACE_H
diff --git a/src/util/error.cpp b/src/util/error.cpp
new file mode 100644
index 000000000..68ffd8b04
--- /dev/null
+++ b/src/util/error.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2010-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/error.h>
+
+#include <util/system.h>
+
+std::string TransactionErrorString(const TransactionError err)
+{
+    switch (err) {
+        case TransactionError::OK:
+            return "No error";
+        case TransactionError::MISSING_INPUTS:
+            return "Missing inputs";
+        case TransactionError::ALREADY_IN_CHAIN:
+            return "Transaction already in block chain";
+        case TransactionError::P2P_DISABLED:
+            return "Peer-to-peer functionality missing or disabled";
+        case TransactionError::MEMPOOL_REJECTED:
+            return "Transaction rejected by AcceptToMemoryPool";
+        case TransactionError::MEMPOOL_ERROR:
+            return "AcceptToMemoryPool failed";
+        case TransactionError::INVALID_PSBT:
+            return "PSBT is not sane";
+        case TransactionError::PSBT_MISMATCH:
+            return "PSBTs not compatible (different transactions)";
+        case TransactionError::SIGHASH_MISMATCH:
+            return "Specified sighash value does not match existing value";
+        // no default case, so the compiler can warn about missing cases
+    }
+    assert(false);
+}
+
+std::string AmountHighWarn(const std::string& optname)
+{
+    return strprintf(_("%s is set very high!"), optname);
+}
+
+std::string AmountErrMsg(const char* const optname, const std::string& strValue)
+{
+    return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
+}
diff --git a/src/util/error.h b/src/util/error.h
new file mode 100644
index 000000000..d93309551
--- /dev/null
+++ b/src/util/error.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2010-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_ERROR_H
+#define BITCOIN_UTIL_ERROR_H
+
+/**
+ * util/error.h is a common place for definitions of simple error types and
+ * string functions. Types and functions defined here should not require any
+ * outside dependencies.
+ *
+ * Error types defined here can be used in different parts of the bitcoin
+ * codebase, to avoid the need to write boilerplate code catching and
+ * translating errors passed across wallet/node/rpc/gui code boundaries.
+ */
+
+#include <string>
+
+enum class TransactionError {
+    OK, //!< No error
+    MISSING_INPUTS,
+    ALREADY_IN_CHAIN,
+    P2P_DISABLED,
+    MEMPOOL_REJECTED,
+    MEMPOOL_ERROR,
+    INVALID_PSBT,
+    PSBT_MISMATCH,
+    SIGHASH_MISMATCH,
+};
+
+std::string TransactionErrorString(const TransactionError error);
+
+std::string AmountHighWarn(const std::string& optname);
+
+std::string AmountErrMsg(const char* const optname, const std::string& strValue);
+
+#endif // BITCOIN_UTIL_ERROR_H
diff --git a/src/util/fees.cpp b/src/util/fees.cpp
new file mode 100644
index 000000000..5fdaa1284
--- /dev/null
+++ b/src/util/fees.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <policy/fees.h>
+
+#include <string>
+
+std::string StringForFeeReason(FeeReason reason) {
+    static const std::map<FeeReason, std::string> fee_reason_strings = {
+        {FeeReason::NONE, "None"},
+        {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
+        {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
+        {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
+        {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
+        {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
+        {FeeReason::PAYTXFEE, "PayTxFee set"},
+        {FeeReason::FALLBACK, "Fallback fee"},
+        {FeeReason::REQUIRED, "Minimum Required Fee"},
+        {FeeReason::MAXTXFEE, "MaxTxFee limit"}
+    };
+    auto reason_string = fee_reason_strings.find(reason);
+
+    if (reason_string == fee_reason_strings.end()) return "Unknown";
+
+    return reason_string->second;
+}
+
+bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
+    static const std::map<std::string, FeeEstimateMode> fee_modes = {
+        {"UNSET", FeeEstimateMode::UNSET},
+        {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
+        {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
+    };
+    auto mode = fee_modes.find(mode_string);
+
+    if (mode == fee_modes.end()) return false;
+
+    fee_estimate_mode = mode->second;
+    return true;
+}
diff --git a/src/util/fees.h b/src/util/fees.h
new file mode 100644
index 000000000..fc355ce9c
--- /dev/null
+++ b/src/util/fees.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_UTIL_FEES_H
+#define BITCOIN_UTIL_FEES_H
+
+#include <string>
+
+enum class FeeEstimateMode;
+enum class FeeReason;
+
+bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
+std::string StringForFeeReason(FeeReason reason);
+
+#endif // BITCOIN_UTIL_FEES_H
diff --git a/src/util/rbf.cpp b/src/util/rbf.cpp
new file mode 100644
index 000000000..d520a9606
--- /dev/null
+++ b/src/util/rbf.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/rbf.h>
+
+#include <primitives/transaction.h>
+
+bool SignalsOptInRBF(const CTransaction &tx)
+{
+    for (const CTxIn &txin : tx.vin) {
+        if (txin.nSequence <= MAX_BIP125_RBF_SEQUENCE) {
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/src/util/rbf.h b/src/util/rbf.h
new file mode 100644
index 000000000..d3ef11062
--- /dev/null
+++ b/src/util/rbf.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_RBF_H
+#define BITCOIN_UTIL_RBF_H
+
+#include <cstdint>
+
+class CTransaction;
+
+static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
+
+// Check whether the sequence numbers on this transaction are signaling
+// opt-in to replace-by-fee, according to BIP 125
+bool SignalsOptInRBF(const CTransaction &tx);
+
+#endif // BITCOIN_UTIL_RBF_H
diff --git a/src/util/url.cpp b/src/util/url.cpp
new file mode 100644
index 000000000..49eacbf2d
--- /dev/null
+++ b/src/util/url.cpp
@@ -0,0 +1,21 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/url.h>
+
+#include <event2/http.h>
+#include <stdlib.h>
+#include <string>
+
+std::string urlDecode(const std::string &urlEncoded) {
+    std::string res;
+    if (!urlEncoded.empty()) {
+        char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
+        if (decoded) {
+            res = std::string(decoded);
+            free(decoded);
+        }
+    }
+    return res;
+}
diff --git a/src/util/url.h b/src/util/url.h
new file mode 100644
index 000000000..3d7315a33
--- /dev/null
+++ b/src/util/url.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_URL_H
+#define BITCOIN_UTIL_URL_H
+
+#include <string>
+
+std::string urlDecode(const std::string &urlEncoded);
+
+#endif // BITCOIN_UTIL_URL_H
diff --git a/src/util/validation.cpp b/src/util/validation.cpp
new file mode 100644
index 000000000..fe1f5a277
--- /dev/null
+++ b/src/util/validation.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/validation.h>
+
+#include <consensus/validation.h>
+#include <tinyformat.h>
+
+/** Convert CValidationState to a human-readable message for logging */
+std::string FormatStateMessage(const CValidationState &state)
+{
+    return strprintf("%s%s (code %i)",
+        state.GetRejectReason(),
+        state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage(),
+        state.GetRejectCode());
+}
+
+const std::string strMessageMagic = "Bitcoin Signed Message:\n";
diff --git a/src/util/validation.h b/src/util/validation.h
new file mode 100644
index 000000000..32559853e
--- /dev/null
+++ b/src/util/validation.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_VALIDATION_H
+#define BITCOIN_UTIL_VALIDATION_H
+
+#include <string>
+
+class CValidationState;
+
+/** Convert CValidationState to a human-readable message for logging */
+std::string FormatStateMessage(const CValidationState &state);
+
+extern const std::string strMessageMagic;
+
+#endif // BITCOIN_UTIL_VALIDATION_H
diff --git a/src/validation.cpp b/src/validation.cpp
index 8cdc7a927..b681d7b75 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -39,8 +39,10 @@
 #include <ui_interface.h>
 #include <undo.h>
 #include <util/moneystr.h>
+#include <util/rbf.h>
 #include <util/strencodings.h>
 #include <util/system.h>
+#include <util/validation.h>
 #include <validationinterface.h>
 #include <warnings.h>
 
@@ -259,8 +261,6 @@ std::atomic_bool g_is_mempool_loaded{false};
 /** Constant stuff for coinbase transactions we create: */
 CScript COINBASE_FLAGS;
 
-const std::string strMessageMagic = "Bitcoin Signed Message:\n";
-
 // Internal stuff
 namespace {
     CBlockIndex *&pindexBestInvalid = g_chainstate.pindexBestInvalid;
@@ -462,15 +462,6 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
         pcoinsTip->Uncache(removed);
 }
 
-/** Convert CValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const CValidationState &state)
-{
-    return strprintf("%s%s (code %i)",
-        state.GetRejectReason(),
-        state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage(),
-        state.GetRejectCode());
-}
-
 static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
 {
     AssertLockHeld(cs_main);
diff --git a/src/validation.h b/src/validation.h
index 673067dc3..9f00cab49 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -150,7 +150,6 @@ extern CTxMemPool mempool;
 extern std::atomic_bool g_is_mempool_loaded;
 typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
 extern BlockMap& mapBlockIndex GUARDED_BY(cs_main);
-extern const std::string strMessageMagic;
 extern Mutex g_best_block_mutex;
 extern std::condition_variable g_best_block_cv;
 extern uint256 g_best_block;
@@ -298,9 +297,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
                         bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
                         bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
 
-/** Convert CValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const CValidationState &state);
-
 /** Get the BIP9 state for a given deployment at the current tip. */
 ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos);
 
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index ef7f3be72..e0f083b8e 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -14,7 +14,9 @@
 #include <validation.h> //for mempool access
 #include <txmempool.h>
 #include <util/moneystr.h>
+#include <util/rbf.h>
 #include <util/system.h>
+#include <util/validation.h>
 #include <net.h>
 
 //! Check whether transaction has descendant in wallet or mempool, or has been
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index a8096dc67..1b4d69bc3 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -9,6 +9,7 @@
 #include <net.h>
 #include <scheduler.h>
 #include <outputtype.h>
+#include <util/error.h>
 #include <util/system.h>
 #include <util/moneystr.h>
 #include <validation.h>
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index de063153c..37e2930ee 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -7,7 +7,6 @@
 #include <chain.h>
 #include <consensus/validation.h>
 #include <core_io.h>
-#include <httpserver.h>
 #include <init.h>
 #include <interfaces/chain.h>
 #include <validation.h>
@@ -27,8 +26,11 @@
 #include <shutdown.h>
 #include <timedata.h>
 #include <util/bip32.h>
+#include <util/fees.h>
 #include <util/system.h>
 #include <util/moneystr.h>
+#include <util/url.h>
+#include <util/validation.h>
 #include <wallet/coincontrol.h>
 #include <wallet/feebumper.h>
 #include <wallet/psbtwallet.h>
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 9f89cbefa..2ef6850a2 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -29,7 +29,11 @@
 #include <timedata.h>
 #include <txmempool.h>
 #include <util/bip32.h>
+#include <util/error.h>
+#include <util/fees.h>
 #include <util/moneystr.h>
+#include <util/rbf.h>
+#include <util/validation.h>
 #include <wallet/fees.h>
 
 #include <algorithm>
diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh
index 7775e7694..87b451dbb 100755
--- a/test/lint/lint-circular-dependencies.sh
+++ b/test/lint/lint-circular-dependencies.sh
@@ -30,8 +30,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
     "wallet/coincontrol -> wallet/wallet -> wallet/coincontrol"
     "wallet/fees -> wallet/wallet -> wallet/fees"
     "wallet/wallet -> wallet/walletdb -> wallet/wallet"
-    "policy/fees -> policy/policy -> validation -> policy/fees"
-    "policy/policy -> validation -> policy/policy"
+    "policy/fees -> txmempool -> validation -> policy/fees"
     "policy/rbf -> txmempool -> validation -> policy/rbf"
     "qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/addressbookpage"
     "qt/guiutil -> qt/walletmodel -> qt/optionsmodel -> qt/guiutil"