aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/bitcoin-cli.bash-completion21
-rw-r--r--src/Makefile.am2
-rw-r--r--src/banman.h1
-rw-r--r--src/bench/coin_selection.cpp7
-rw-r--r--src/bench/wallet_balance.cpp4
-rw-r--r--src/bitcoin-cli.cpp2
-rw-r--r--src/bitcoind.cpp17
-rw-r--r--src/chainparams.cpp6
-rw-r--r--src/crypto/hkdf_sha256_32.cpp2
-rw-r--r--src/dummywallet.cpp2
-rw-r--r--src/fs.cpp4
-rw-r--r--src/httprpc.cpp2
-rw-r--r--src/init.cpp65
-rw-r--r--src/init.h22
-rw-r--r--src/interfaces/chain.cpp7
-rw-r--r--src/interfaces/chain.h3
-rw-r--r--src/interfaces/node.cpp55
-rw-r--r--src/interfaces/node.h4
-rw-r--r--src/interfaces/wallet.cpp6
-rw-r--r--src/net.h2
-rw-r--r--src/net_processing.cpp10
-rw-r--r--src/node/context.cpp13
-rw-r--r--src/node/context.h44
-rw-r--r--src/node/transaction.cpp11
-rw-r--r--src/node/transaction.h5
-rw-r--r--src/qt/test/addressbooktests.cpp12
-rw-r--r--src/qt/test/addressbooktests.h8
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/qt/test/rpcnestedtests.h8
-rw-r--r--src/qt/test/test_main.cpp8
-rw-r--r--src/qt/test/wallettests.cpp13
-rw-r--r--src/qt/test/wallettests.h8
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/rpc/blockchain.h6
-rw-r--r--src/rpc/mining.cpp5
-rw-r--r--src/rpc/net.cpp96
-rw-r--r--src/rpc/rawtransaction.cpp4
-rw-r--r--src/rpc/util.cpp2
-rw-r--r--src/rpc/util.h6
-rw-r--r--src/test/rpc_tests.cpp10
-rw-r--r--src/test/setup_common.cpp11
-rw-r--r--src/test/setup_common.h2
-rw-r--r--src/test/transaction_tests.cpp16
-rw-r--r--src/util/strencodings.cpp4
-rw-r--r--src/wallet/crypter.cpp2
-rw-r--r--src/wallet/init.cpp9
-rw-r--r--src/wallet/rpcwallet.cpp8
-rw-r--r--src/wallet/rpcwallet.h6
-rw-r--r--src/wallet/test/coinselector_tests.cpp4
-rw-r--r--src/wallet/test/init_test_fixture.h4
-rw-r--r--src/wallet/test/ismine_tests.cpp4
-rw-r--r--src/wallet/test/wallet_test_fixture.h4
-rw-r--r--src/wallet/test/wallet_tests.cpp19
-rw-r--r--src/walletinitinterface.h6
54 files changed, 367 insertions, 239 deletions
diff --git a/contrib/bitcoin-cli.bash-completion b/contrib/bitcoin-cli.bash-completion
index f4cac84182..f7f12a2773 100644
--- a/contrib/bitcoin-cli.bash-completion
+++ b/contrib/bitcoin-cli.bash-completion
@@ -17,13 +17,6 @@ _bitcoin_rpc() {
$bitcoin_cli "${rpcargs[@]}" "$@"
}
-# Add wallet accounts to COMPREPLY
-_bitcoin_accounts() {
- local accounts
- accounts=$(_bitcoin_rpc listaccounts | awk -F '"' '{ print $2 }')
- COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) )
-}
-
_bitcoin_cli() {
local cur prev words=() cword
local bitcoin_cli
@@ -60,10 +53,9 @@ _bitcoin_cli() {
if ((cword > 3)); then
case ${words[cword-3]} in
addmultisigaddress)
- _bitcoin_accounts
return 0
;;
- getbalance|gettxout|importaddress|importpubkey|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock)
+ getbalance|gettxout|importaddress|importpubkey|importprivkey|listreceivedbyaddress|listsinceblock)
COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
return 0
;;
@@ -80,14 +72,10 @@ _bitcoin_cli() {
COMPREPLY=( $( compgen -W "add remove" -- "$cur" ) )
return 0
;;
- fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction)
+ fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listreceivedbyaddress|sendrawtransaction)
COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
return 0
;;
- move|setaccount)
- _bitcoin_accounts
- return 0
- ;;
esac
fi
@@ -96,12 +84,11 @@ _bitcoin_cli() {
_filedir
return 0
;;
- getaddednodeinfo|getrawmempool|lockunspent|setgenerate)
+ getaddednodeinfo|getrawmempool|lockunspent)
COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
return 0
;;
- getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany)
- _bitcoin_accounts
+ getbalance|getnewaddress|listtransactions|sendmany)
return 0
;;
esac
diff --git a/src/Makefile.am b/src/Makefile.am
index 3fb1a1f982..619f968bc9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -157,6 +157,7 @@ BITCOIN_CORE_H = \
netmessagemaker.h \
node/coin.h \
node/coinstats.h \
+ node/context.h \
node/psbt.h \
node/transaction.h \
noui.h \
@@ -285,6 +286,7 @@ libbitcoin_server_a_SOURCES = \
net_processing.cpp \
node/coin.cpp \
node/coinstats.cpp \
+ node/context.cpp \
node/psbt.cpp \
node/transaction.cpp \
noui.cpp \
diff --git a/src/banman.h b/src/banman.h
index a1a00309dd..9d45bf0559 100644
--- a/src/banman.h
+++ b/src/banman.h
@@ -66,5 +66,4 @@ private:
const int64_t m_default_ban_time;
};
-extern std::unique_ptr<BanMan> g_banman;
#endif
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index f2ab03e20e..29a145bfe6 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -4,6 +4,7 @@
#include <bench/bench.h>
#include <interfaces/chain.h>
+#include <node/context.h>
#include <wallet/coinselection.h>
#include <wallet/wallet.h>
@@ -28,7 +29,8 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<st
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CoinSelection(benchmark::State& state)
{
- auto chain = interfaces::MakeChain();
+ NodeContext node;
+ auto chain = interfaces::MakeChain(node);
const CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxs;
LOCK(wallet.cs_wallet);
@@ -60,7 +62,8 @@ static void CoinSelection(benchmark::State& state)
}
typedef std::set<CInputCoin> CoinSet;
-static auto testChain = interfaces::MakeChain();
+static NodeContext testNode;
+static auto testChain = interfaces::MakeChain(testNode);
static const CWallet testWallet(testChain.get(), WalletLocation(), WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxn;
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index 313b5a3ba0..0e660d6bcd 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -4,6 +4,7 @@
#include <bench/bench.h>
#include <interfaces/chain.h>
+#include <node/context.h>
#include <optional.h>
#include <test/util.h>
#include <validationinterface.h>
@@ -13,7 +14,8 @@ static void WalletBalance(benchmark::State& state, const bool set_dirty, const b
{
const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain();
+ NodeContext node;
+ std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
CWallet wallet{chain.get(), WalletLocation(), WalletDatabase::CreateMock()};
{
bool first_run;
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 1b20d4afda..d7b6891503 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -368,7 +368,7 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
std::string endpoint = "/";
if (!gArgs.GetArgs("-rpcwallet").empty()) {
std::string walletName = gArgs.GetArg("-rpcwallet", "");
- char *encodedURI = evhttp_uriencode(walletName.c_str(), walletName.size(), false);
+ char *encodedURI = evhttp_uriencode(walletName.data(), walletName.size(), false);
if (encodedURI) {
endpoint = "/wallet/"+ std::string(encodedURI);
free(encodedURI);
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 70c308960c..4b5cea4849 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -12,6 +12,7 @@
#include <compat.h>
#include <init.h>
#include <interfaces/chain.h>
+#include <node/context.h>
#include <noui.h>
#include <shutdown.h>
#include <ui_interface.h>
@@ -24,13 +25,13 @@
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
-static void WaitForShutdown()
+static void WaitForShutdown(NodeContext& node)
{
while (!ShutdownRequested())
{
MilliSleep(200);
}
- Interrupt();
+ Interrupt(node);
}
//////////////////////////////////////////////////////////////////////////////
@@ -39,8 +40,8 @@ static void WaitForShutdown()
//
static bool AppInit(int argc, char* argv[])
{
- InitInterfaces interfaces;
- interfaces.chain = interfaces::MakeChain();
+ NodeContext node;
+ node.chain = interfaces::MakeChain(node);
bool fRet = false;
@@ -142,7 +143,7 @@ static bool AppInit(int argc, char* argv[])
// If locking the data directory failed, exit immediately
return false;
}
- fRet = AppInitMain(interfaces);
+ fRet = AppInitMain(node);
}
catch (const std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
@@ -152,11 +153,11 @@ static bool AppInit(int argc, char* argv[])
if (!fRet)
{
- Interrupt();
+ Interrupt(node);
} else {
- WaitForShutdown();
+ WaitForShutdown(node);
}
- Shutdown(interfaces);
+ Shutdown(node);
return fRet;
}
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 7ff30ac1cd..dd4d3e97ac 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -62,7 +62,7 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
class CMainParams : public CChainParams {
public:
CMainParams() {
- strNetworkID = "main";
+ strNetworkID = CBaseChainParams::MAIN;
consensus.nSubsidyHalvingInterval = 210000;
consensus.BIP16Exception = uint256S("0x00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22");
consensus.BIP34Height = 227931;
@@ -169,7 +169,7 @@ public:
class CTestNetParams : public CChainParams {
public:
CTestNetParams() {
- strNetworkID = "test";
+ strNetworkID = CBaseChainParams::TESTNET;
consensus.nSubsidyHalvingInterval = 210000;
consensus.BIP16Exception = uint256S("0x00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105");
consensus.BIP34Height = 21111;
@@ -254,7 +254,7 @@ public:
class CRegTestParams : public CChainParams {
public:
explicit CRegTestParams(const ArgsManager& args) {
- strNetworkID = "regtest";
+ strNetworkID = CBaseChainParams::REGTEST;
consensus.nSubsidyHalvingInterval = 150;
consensus.BIP16Exception = uint256();
consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests)
diff --git a/src/crypto/hkdf_sha256_32.cpp b/src/crypto/hkdf_sha256_32.cpp
index 9cea5995ec..e684eced37 100644
--- a/src/crypto/hkdf_sha256_32.cpp
+++ b/src/crypto/hkdf_sha256_32.cpp
@@ -9,7 +9,7 @@
CHKDF_HMAC_SHA256_L32::CHKDF_HMAC_SHA256_L32(const unsigned char* ikm, size_t ikmlen, const std::string& salt)
{
- CHMAC_SHA256((const unsigned char*)salt.c_str(), salt.size()).Write(ikm, ikmlen).Finalize(m_prk);
+ CHMAC_SHA256((const unsigned char*)salt.data(), salt.size()).Write(ikm, ikmlen).Finalize(m_prk);
}
void CHKDF_HMAC_SHA256_L32::Expand32(const std::string& info, unsigned char hash[OUTPUT_SIZE])
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
index 0edcb0286d..38b5b0efc4 100644
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.cpp
@@ -19,7 +19,7 @@ public:
bool HasWalletSupport() const override {return false;}
void AddWalletOptions() const override;
bool ParameterInteraction() const override {return true;}
- void Construct(InitInterfaces& interfaces) const override {LogPrintf("No wallet support compiled in!\n");}
+ void Construct(NodeContext& node) const override {LogPrintf("No wallet support compiled in!\n");}
};
void DummyWalletInit::AddWalletOptions() const
diff --git a/src/fs.cpp b/src/fs.cpp
index 7b422b8d70..73fb3b606e 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -107,10 +107,10 @@ std::string get_filesystem_error_message(const fs::filesystem_error& e)
#else
// Convert from Multi Byte to utf-16
std::string mb_string(e.what());
- int size = MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), nullptr, 0);
+ int size = MultiByteToWideChar(CP_ACP, 0, mb_string.data(), mb_string.size(), nullptr, 0);
std::wstring utf16_string(size, L'\0');
- MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), &*utf16_string.begin(), size);
+ MultiByteToWideChar(CP_ACP, 0, mb_string.data(), mb_string.size(), &*utf16_string.begin(), size);
// Convert from utf-16 to utf-8
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(utf16_string);
#endif
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 2c2f67b169..0437f0c7de 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -112,7 +112,7 @@ static bool multiUserAuthorized(std::string strUserPass)
static const unsigned int KEY_SIZE = 32;
unsigned char out[KEY_SIZE];
- CHMAC_SHA256(reinterpret_cast<const unsigned char*>(strSalt.c_str()), strSalt.size()).Write(reinterpret_cast<const unsigned char*>(strPass.c_str()), strPass.size()).Finalize(out);
+ CHMAC_SHA256(reinterpret_cast<const unsigned char*>(strSalt.data()), strSalt.size()).Write(reinterpret_cast<const unsigned char*>(strPass.data()), strPass.size()).Finalize(out);
std::vector<unsigned char> hexvec(out, out+KEY_SIZE);
std::string strHashFromPass = HexStr(hexvec);
diff --git a/src/init.cpp b/src/init.cpp
index 93221efe9b..ef017efbb9 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -29,6 +29,7 @@
#include <net_permissions.h>
#include <net_processing.h>
#include <netbase.h>
+#include <node/context.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
@@ -84,9 +85,6 @@ static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
// Dump addresses to banlist.dat every 15 minutes (900s)
static constexpr int DUMP_BANS_INTERVAL = 60 * 15;
-std::unique_ptr<CConnman> g_connman;
-std::unique_ptr<PeerLogicValidation> peerLogic;
-std::unique_ptr<BanMan> g_banman;
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
@@ -154,7 +152,7 @@ static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
static boost::thread_group threadGroup;
static CScheduler scheduler;
-void Interrupt()
+void Interrupt(NodeContext& node)
{
InterruptHTTPServer();
InterruptHTTPRPC();
@@ -162,15 +160,15 @@ void Interrupt()
InterruptREST();
InterruptTorControl();
InterruptMapPort();
- if (g_connman)
- g_connman->Interrupt();
+ if (node.connman)
+ node.connman->Interrupt();
if (g_txindex) {
g_txindex->Interrupt();
}
ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Interrupt(); });
}
-void Shutdown(InitInterfaces& interfaces)
+void Shutdown(NodeContext& node)
{
LogPrintf("%s: In progress...\n", __func__);
static CCriticalSection cs_Shutdown;
@@ -189,15 +187,15 @@ void Shutdown(InitInterfaces& interfaces)
StopREST();
StopRPC();
StopHTTPServer();
- for (const auto& client : interfaces.chain_clients) {
+ for (const auto& client : node.chain_clients) {
client->flush();
}
StopMapPort();
// Because these depend on each-other, we make sure that neither can be
// using the other before destroying them.
- if (peerLogic) UnregisterValidationInterface(peerLogic.get());
- if (g_connman) g_connman->Stop();
+ if (node.peer_logic) UnregisterValidationInterface(node.peer_logic.get());
+ if (node.connman) node.connman->Stop();
if (g_txindex) g_txindex->Stop();
ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Stop(); });
@@ -210,9 +208,9 @@ void Shutdown(InitInterfaces& interfaces)
// After the threads that potentially access these pointers have been stopped,
// destruct and reset all to nullptr.
- peerLogic.reset();
- g_connman.reset();
- g_banman.reset();
+ node.peer_logic.reset();
+ node.connman.reset();
+ node.banman.reset();
g_txindex.reset();
DestroyAllBlockFilterIndexes();
@@ -261,7 +259,7 @@ void Shutdown(InitInterfaces& interfaces)
}
pblocktree.reset();
}
- for (const auto& client : interfaces.chain_clients) {
+ for (const auto& client : node.chain_clients) {
client->stop();
}
@@ -280,7 +278,7 @@ void Shutdown(InitInterfaces& interfaces)
} catch (const fs::filesystem_error& e) {
LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
}
- interfaces.chain_clients.clear();
+ node.chain_clients.clear();
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);
@@ -1207,7 +1205,7 @@ bool AppInitLockDataDirectory()
return true;
}
-bool AppInitMain(InitInterfaces& interfaces)
+bool AppInitMain(NodeContext& node)
{
const CChainParams& chainparams = Params();
// ********************************************************* Step 4a: application initialization
@@ -1275,16 +1273,16 @@ bool AppInitMain(InitInterfaces& interfaces)
// according to -wallet and -disablewallet options. This only constructs
// the interfaces, it doesn't load wallet data. Wallets actually get loaded
// when load() and start() interface methods are called below.
- g_wallet_init_interface.Construct(interfaces);
+ g_wallet_init_interface.Construct(node);
/* Register RPC commands regardless of -server setting so they will be
* available in the GUI RPC console even if external calls are disabled.
*/
RegisterAllCoreRPCCommands(tableRPC);
- for (const auto& client : interfaces.chain_clients) {
+ for (const auto& client : node.chain_clients) {
client->registerRpcs();
}
- g_rpc_interfaces = &interfaces;
+ g_rpc_node = &node;
#if ENABLE_ZMQ
RegisterZMQRPCCommands(tableRPC);
#endif
@@ -1302,7 +1300,7 @@ bool AppInitMain(InitInterfaces& interfaces)
}
// ********************************************************* Step 5: verify wallet database integrity
- for (const auto& client : interfaces.chain_clients) {
+ for (const auto& client : node.chain_clients) {
if (!client->verify()) {
return false;
}
@@ -1314,13 +1312,13 @@ bool AppInitMain(InitInterfaces& interfaces)
// is not yet setup and may end up being set up twice if we
// need to reindex later.
- assert(!g_banman);
- g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
- assert(!g_connman);
- g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
+ assert(!node.banman);
+ node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
+ assert(!node.connman);
+ node.connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
- peerLogic.reset(new PeerLogicValidation(g_connman.get(), g_banman.get(), scheduler));
- RegisterValidationInterface(peerLogic.get());
+ node.peer_logic.reset(new PeerLogicValidation(node.connman.get(), node.banman.get(), scheduler));
+ RegisterValidationInterface(node.peer_logic.get());
// sanitize comments per BIP-0014, format user agent and check total size
std::vector<std::string> uacomments;
@@ -1661,7 +1659,7 @@ bool AppInitMain(InitInterfaces& interfaces)
}
// ********************************************************* Step 9: load wallet
- for (const auto& client : interfaces.chain_clients) {
+ for (const auto& client : node.chain_clients) {
if (!client->load()) {
return false;
}
@@ -1765,8 +1763,8 @@ bool AppInitMain(InitInterfaces& interfaces)
connOptions.nMaxFeeler = 1;
connOptions.nBestHeight = chain_active_height;
connOptions.uiInterface = &uiInterface;
- connOptions.m_banman = g_banman.get();
- connOptions.m_msgproc = peerLogic.get();
+ connOptions.m_banman = node.banman.get();
+ connOptions.m_msgproc = node.peer_logic.get();
connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
connOptions.m_added_nodes = gArgs.GetArgs("-addnode");
@@ -1806,7 +1804,7 @@ bool AppInitMain(InitInterfaces& interfaces)
connOptions.m_specified_outgoing = connect;
}
}
- if (!g_connman->Start(scheduler, connOptions)) {
+ if (!node.connman->Start(scheduler, connOptions)) {
return false;
}
@@ -1815,12 +1813,13 @@ bool AppInitMain(InitInterfaces& interfaces)
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading").translated);
- for (const auto& client : interfaces.chain_clients) {
+ for (const auto& client : node.chain_clients) {
client->start(scheduler);
}
- scheduler.scheduleEvery([]{
- g_banman->DumpBanlist();
+ BanMan* banman = node.banman.get();
+ scheduler.scheduleEvery([banman]{
+ banman->DumpBanlist();
}, DUMP_BANS_INTERVAL * 1000);
return true;
diff --git a/src/init.h b/src/init.h
index 1c59ca069e..ca52dadf08 100644
--- a/src/init.h
+++ b/src/init.h
@@ -10,26 +10,14 @@
#include <string>
#include <util/system.h>
-namespace interfaces {
-class Chain;
-class ChainClient;
-} // namespace interfaces
-
-//! Pointers to interfaces used during init and destroyed on shutdown.
-struct InitInterfaces
-{
- std::unique_ptr<interfaces::Chain> chain;
- std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
-};
-
-namespace boost
-{
+struct NodeContext;
+namespace boost {
class thread_group;
} // namespace boost
/** Interrupt threads */
-void Interrupt();
-void Shutdown(InitInterfaces& interfaces);
+void Interrupt(NodeContext& node);
+void Shutdown(NodeContext& node);
//!Initialize the logging infrastructure
void InitLogging();
//!Parameter interaction: change current parameters depending on various rules
@@ -63,7 +51,7 @@ bool AppInitLockDataDirectory();
* @note This should only be done after daemonization. Call Shutdown() if this function fails.
* @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called.
*/
-bool AppInitMain(InitInterfaces& interfaces);
+bool AppInitMain(NodeContext& node);
/**
* Setup the arguments for gArgs
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index b2c20573fb..23099a7799 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -11,6 +11,7 @@
#include <net.h>
#include <net_processing.h>
#include <node/coin.h>
+#include <node/context.h>
#include <node/transaction.h>
#include <policy/fees.h>
#include <policy/policy.h>
@@ -238,6 +239,7 @@ public:
class ChainImpl : public Chain
{
public:
+ explicit ChainImpl(NodeContext& node) : m_node(node) {}
std::unique_ptr<Chain::Lock> lock(bool try_lock) override
{
auto result = MakeUnique<LockImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
@@ -286,7 +288,7 @@ public:
}
bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) override
{
- const TransactionError err = BroadcastTransaction(tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
+ const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
// Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
// Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures
// that Chain clients do not need to know about.
@@ -378,9 +380,10 @@ public:
notifications.TransactionAddedToMempool(entry.GetSharedTx());
}
}
+ NodeContext& m_node;
};
} // namespace
-std::unique_ptr<Chain> MakeChain() { return MakeUnique<ChainImpl>(); }
+std::unique_ptr<Chain> MakeChain(NodeContext& node) { return MakeUnique<ChainImpl>(node); }
} // namespace interfaces
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 73a78e21fb..3fe12088c5 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -24,6 +24,7 @@ class uint256;
enum class RBFTransactionState;
struct CBlockLocator;
struct FeeCalculation;
+struct NodeContext;
namespace interfaces {
@@ -291,7 +292,7 @@ public:
};
//! Return implementation of Chain interface.
-std::unique_ptr<Chain> MakeChain();
+std::unique_ptr<Chain> MakeChain(NodeContext& node);
//! Return implementation of ChainClient interface for a wallet client. This
//! function will be undefined in builds where ENABLE_WALLET is false.
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 6577895d50..1877c92178 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -16,6 +16,7 @@
#include <net_processing.h>
#include <netaddress.h>
#include <netbase.h>
+#include <node/context.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/settings.h>
@@ -52,7 +53,6 @@ namespace {
class NodeImpl : public Node
{
public:
- NodeImpl() { m_interfaces.chain = MakeChain(); }
void initError(const std::string& message) override { InitError(message); }
bool parseParameters(int argc, const char* const argv[], std::string& error) override
{
@@ -75,11 +75,15 @@ public:
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
AppInitLockDataDirectory();
}
- bool appInitMain() override { return AppInitMain(m_interfaces); }
+ bool appInitMain() override
+ {
+ m_context.chain = MakeChain(m_context);
+ return AppInitMain(m_context);
+ }
void appShutdown() override
{
- Interrupt();
- Shutdown(m_interfaces);
+ Interrupt(m_context);
+ Shutdown(m_context);
}
void startShutdown() override { StartShutdown(); }
bool shutdownRequested() override { return ShutdownRequested(); }
@@ -96,15 +100,15 @@ public:
bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
size_t getNodeCount(CConnman::NumConnections flags) override
{
- return g_connman ? g_connman->GetNodeCount(flags) : 0;
+ return m_context.connman ? m_context.connman->GetNodeCount(flags) : 0;
}
bool getNodesStats(NodesStats& stats) override
{
stats.clear();
- if (g_connman) {
+ if (m_context.connman) {
std::vector<CNodeStats> stats_temp;
- g_connman->GetNodeStats(stats_temp);
+ m_context.connman->GetNodeStats(stats_temp);
stats.reserve(stats_temp.size());
for (auto& node_stats_temp : stats_temp) {
@@ -125,44 +129,44 @@ public:
}
bool getBanned(banmap_t& banmap) override
{
- if (g_banman) {
- g_banman->GetBanned(banmap);
+ if (m_context.banman) {
+ m_context.banman->GetBanned(banmap);
return true;
}
return false;
}
bool ban(const CNetAddr& net_addr, BanReason reason, int64_t ban_time_offset) override
{
- if (g_banman) {
- g_banman->Ban(net_addr, reason, ban_time_offset);
+ if (m_context.banman) {
+ m_context.banman->Ban(net_addr, reason, ban_time_offset);
return true;
}
return false;
}
bool unban(const CSubNet& ip) override
{
- if (g_banman) {
- g_banman->Unban(ip);
+ if (m_context.banman) {
+ m_context.banman->Unban(ip);
return true;
}
return false;
}
bool disconnect(const CNetAddr& net_addr) override
{
- if (g_connman) {
- return g_connman->DisconnectNode(net_addr);
+ if (m_context.connman) {
+ return m_context.connman->DisconnectNode(net_addr);
}
return false;
}
bool disconnect(NodeId id) override
{
- if (g_connman) {
- return g_connman->DisconnectNode(id);
+ if (m_context.connman) {
+ return m_context.connman->DisconnectNode(id);
}
return false;
}
- int64_t getTotalBytesRecv() override { return g_connman ? g_connman->GetTotalBytesRecv() : 0; }
- int64_t getTotalBytesSent() override { return g_connman ? g_connman->GetTotalBytesSent() : 0; }
+ int64_t getTotalBytesRecv() override { return m_context.connman ? m_context.connman->GetTotalBytesRecv() : 0; }
+ int64_t getTotalBytesSent() override { return m_context.connman ? m_context.connman->GetTotalBytesSent() : 0; }
size_t getMempoolSize() override { return ::mempool.size(); }
size_t getMempoolDynamicUsage() override { return ::mempool.DynamicMemoryUsage(); }
bool getHeaderTip(int& height, int64_t& block_time) override
@@ -202,11 +206,11 @@ public:
bool getImporting() override { return ::fImporting; }
void setNetworkActive(bool active) override
{
- if (g_connman) {
- g_connman->SetNetworkActive(active);
+ if (m_context.connman) {
+ m_context.connman->SetNetworkActive(active);
}
}
- bool getNetworkActive() override { return g_connman && g_connman->GetNetworkActive(); }
+ bool getNetworkActive() override { return m_context.connman && m_context.connman->GetNetworkActive(); }
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
{
FeeCalculation fee_calc;
@@ -255,12 +259,12 @@ public:
}
std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) override
{
- return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warnings));
+ return MakeWallet(LoadWallet(*m_context.chain, name, error, warnings));
}
WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) override
{
std::shared_ptr<CWallet> wallet;
- WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
+ WalletCreationStatus status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
result = MakeWallet(wallet);
return status;
}
@@ -315,7 +319,8 @@ public:
/* verification progress is unused when a header was received */ 0);
}));
}
- InitInterfaces m_interfaces;
+ NodeContext* context() override { return &m_context; }
+ NodeContext m_context;
};
} // namespace
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 4ee467014c..c29037f2e3 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -28,6 +28,7 @@ class RPCTimerInterface;
class UniValue;
class proxyType;
struct CNodeStateStats;
+struct NodeContext;
enum class WalletCreationStatus;
namespace interfaces {
@@ -254,6 +255,9 @@ public:
using NotifyHeaderTipFn =
std::function<void(bool initial_download, int height, int64_t block_time, double verification_progress)>;
virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;
+
+ //! Return pointer to internal chain interface, useful for testing.
+ virtual NodeContext* context() { return nullptr; }
};
//! Return implementation of Node interface.
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 6bccde1b8f..b6ede08b14 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -496,7 +496,11 @@ public:
: m_chain(chain), m_wallet_filenames(std::move(wallet_filenames))
{
}
- void registerRpcs() override { return RegisterWalletRPCCommands(m_chain, m_rpc_handlers); }
+ void registerRpcs() override
+ {
+ g_rpc_chain = &m_chain;
+ return RegisterWalletRPCCommands(m_chain, m_rpc_handlers);
+ }
bool verify() override { return VerifyWallets(m_chain, m_wallet_filenames); }
bool load() override { return LoadWallets(m_chain, m_wallet_filenames); }
void start(CScheduler& scheduler) override { return StartWallets(scheduler); }
diff --git a/src/net.h b/src/net.h
index af73361c08..1bbcc89478 100644
--- a/src/net.h
+++ b/src/net.h
@@ -480,8 +480,6 @@ private:
friend struct CConnmanTest;
};
-extern std::unique_ptr<CConnman> g_connman;
-extern std::unique_ptr<BanMan> g_banman;
void Discover();
void StartMapPort();
void InterruptMapPort();
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index fd31c962c2..836da0be70 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1860,7 +1860,7 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
}
}
-bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
+bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc)
{
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
@@ -2136,7 +2136,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
addr.nTime = nNow - 5 * 24 * 60 * 60;
pfrom->AddAddressKnown(addr);
- if (g_banman->IsBanned(addr)) continue; // Do not process banned addresses beyond remembering we received them
+ if (banman->IsBanned(addr)) continue; // Do not process banned addresses beyond remembering we received them
bool fReachable = IsReachable(addr);
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
@@ -2772,7 +2772,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
} // cs_main
if (fProcessBLOCKTXN)
- return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, interruptMsgProc);
+ return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, banman, interruptMsgProc);
if (fRevertToHeaderProcessing) {
// Headers received from HB compact block peers are permitted to be
@@ -2990,7 +2990,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::vector<CAddress> vAddr = connman->GetAddresses();
FastRandomContext insecure_rand;
for (const CAddress &addr : vAddr) {
- if (!g_banman->IsBanned(addr)) {
+ if (!banman->IsBanned(addr)) {
pfrom->PushAddress(addr, insecure_rand);
}
}
@@ -3310,7 +3310,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
bool fRet = false;
try
{
- fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.m_time, chainparams, connman, interruptMsgProc);
+ fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.m_time, chainparams, connman, m_banman, interruptMsgProc);
if (interruptMsgProc)
return false;
if (!pfrom->vRecvGetData.empty())
diff --git a/src/node/context.cpp b/src/node/context.cpp
new file mode 100644
index 0000000000..26a01420c8
--- /dev/null
+++ b/src/node/context.cpp
@@ -0,0 +1,13 @@
+// Copyright (c) 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 <node/context.h>
+
+#include <banman.h>
+#include <interfaces/chain.h>
+#include <net.h>
+#include <net_processing.h>
+
+NodeContext::NodeContext() {}
+NodeContext::~NodeContext() {}
diff --git a/src/node/context.h b/src/node/context.h
new file mode 100644
index 0000000000..2b124af4db
--- /dev/null
+++ b/src/node/context.h
@@ -0,0 +1,44 @@
+// Copyright (c) 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_NODE_CONTEXT_H
+#define BITCOIN_NODE_CONTEXT_H
+
+#include <memory>
+#include <vector>
+
+class BanMan;
+class CConnman;
+class PeerLogicValidation;
+namespace interfaces {
+class Chain;
+class ChainClient;
+} // namespace interfaces
+
+//! NodeContext struct containing references to chain state and connection
+//! state.
+//!
+//! This is used by init, rpc, and test code to pass object references around
+//! without needing to declare the same variables and parameters repeatedly, or
+//! to use globals. More variables could be added to this struct (particularly
+//! references to validation and mempool objects) to eliminate use of globals
+//! and make code more modular and testable. The struct isn't intended to have
+//! any member functions. It should just be a collection of references that can
+//! be used without pulling in unwanted dependencies or functionality.
+struct NodeContext
+{
+ std::unique_ptr<CConnman> connman;
+ std::unique_ptr<PeerLogicValidation> peer_logic;
+ std::unique_ptr<BanMan> banman;
+ std::unique_ptr<interfaces::Chain> chain;
+ std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
+
+ //! Declare default constructor and destructor that are not inline, so code
+ //! instantiating the NodeContext struct doesn't need to #include class
+ //! definitions for all the unique_ptr members.
+ NodeContext();
+ ~NodeContext();
+};
+
+#endif // BITCOIN_NODE_CONTEXT_H
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 7783671a6c..ba4f3c5370 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -6,6 +6,7 @@
#include <consensus/validation.h>
#include <net.h>
#include <net_processing.h>
+#include <node/context.h>
#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
@@ -13,12 +14,12 @@
#include <future>
-TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
+TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
{
// BroadcastTransaction can be called by either sendrawtransaction RPC or wallet RPCs.
- // g_connman is assigned both before chain clients and before RPC server is accepting calls,
- // and reset after chain clients and RPC sever are stopped. g_connman should never be null here.
- assert(g_connman);
+ // node.connman is assigned both before chain clients and before RPC server is accepting calls,
+ // and reset after chain clients and RPC sever are stopped. node.connman should never be null here.
+ assert(node.connman);
std::promise<void> promise;
uint256 hashTx = tx->GetHash();
bool callback_set = false;
@@ -79,7 +80,7 @@ TransactionError BroadcastTransaction(const CTransactionRef tx, std::string& err
}
if (relay) {
- RelayTransaction(hashTx, *g_connman);
+ RelayTransaction(hashTx, *node.connman);
}
return TransactionError::OK;
diff --git a/src/node/transaction.h b/src/node/transaction.h
index a3e56544a7..35873d8376 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -9,6 +9,8 @@
#include <primitives/transaction.h>
#include <util/error.h>
+struct NodeContext;
+
/**
* Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
*
@@ -18,6 +20,7 @@
* NOT be set while cs_main, cs_mempool or cs_wallet are held to avoid
* deadlock.
*
+ * @param[in] node reference to node context
* @param[in] tx the transaction to broadcast
* @param[out] &err_string reference to std::string to fill with error string if available
* @param[in] max_tx_fee reject txs with fees higher than this (if 0, accept any fee)
@@ -25,6 +28,6 @@
* @param[in] wait_callback, wait until callbacks have been processed to avoid stale result due to a sequentially RPC.
* return error
*/
-NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
+NODISCARD TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
#endif // BITCOIN_NODE_TRANSACTION_H
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 4fe440a679..8b32b70d1e 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -51,11 +51,10 @@ void EditAddressAndSubmit(
* In each case, verify the resulting state of the address book and optionally
* the warning message presented to the user.
*/
-void TestAddAddressesToSendBook()
+void TestAddAddressesToSendBook(interfaces::Node& node)
{
TestChain100Setup test;
- auto chain = interfaces::MakeChain();
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateMock());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
@@ -101,10 +100,9 @@ void TestAddAddressesToSendBook()
// Initialize relevant QT models.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
- auto node = interfaces::MakeNode();
- OptionsModel optionsModel(*node);
+ OptionsModel optionsModel(node);
AddWallet(wallet);
- WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &optionsModel);
+ WalletModel walletModel(interfaces::MakeWallet(wallet), node, platformStyle.get(), &optionsModel);
RemoveWallet(wallet);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());
@@ -150,5 +148,5 @@ void AddressBookTests::addressBookTests()
return;
}
#endif
- TestAddAddressesToSendBook();
+ TestAddAddressesToSendBook(m_node);
}
diff --git a/src/qt/test/addressbooktests.h b/src/qt/test/addressbooktests.h
index beeb9e76a9..9944750ec8 100644
--- a/src/qt/test/addressbooktests.h
+++ b/src/qt/test/addressbooktests.h
@@ -4,8 +4,16 @@
#include <QObject>
#include <QTest>
+namespace interfaces {
+class Node;
+} // namespace interfaces
+
class AddressBookTests : public QObject
{
+public:
+ AddressBookTests(interfaces::Node& node) : m_node(node) {}
+ interfaces::Node& m_node;
+
Q_OBJECT
private Q_SLOTS:
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index 3c2ffa6c00..1772de4c1b 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -41,7 +41,7 @@ void RPCNestedTests::rpcNestedTests()
std::string result;
std::string result2;
std::string filtered;
- auto node = interfaces::MakeNode();
+ interfaces::Node* node = &m_node;
RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
QVERIFY(result=="main");
QVERIFY(filtered == "getblockchaininfo()[chain]");
diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h
index 97143ff78a..8789fe8373 100644
--- a/src/qt/test/rpcnestedtests.h
+++ b/src/qt/test/rpcnestedtests.h
@@ -8,8 +8,16 @@
#include <QObject>
#include <QTest>
+namespace interfaces {
+class Node;
+} // namespace interfaces
+
class RPCNestedTests : public QObject
{
+public:
+ RPCNestedTests(interfaces::Node& node) : m_node(node) {}
+ interfaces::Node& m_node;
+
Q_OBJECT
private Q_SLOTS:
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index f272627f96..e6870cf1be 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
BasicTestingSetup dummy{CBaseChainParams::REGTEST};
}
- auto node = interfaces::MakeNode();
+ std::unique_ptr<interfaces::Node> node = interfaces::MakeNode();
bool fInvalid = false;
@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
if (QTest::qExec(&test1) != 0) {
fInvalid = true;
}
- RPCNestedTests test3;
+ RPCNestedTests test3(*node);
if (QTest::qExec(&test3) != 0) {
fInvalid = true;
}
@@ -85,11 +85,11 @@ int main(int argc, char *argv[])
fInvalid = true;
}
#ifdef ENABLE_WALLET
- WalletTests test5;
+ WalletTests test5(*node);
if (QTest::qExec(&test5) != 0) {
fInvalid = true;
}
- AddressBookTests test6;
+ AddressBookTests test6(*node);
if (QTest::qExec(&test6) != 0) {
fInvalid = true;
}
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 379bd8af88..881653cdac 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -126,15 +126,15 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st
// QT_QPA_PLATFORM=xcb src/qt/test/test_bitcoin-qt # Linux
// QT_QPA_PLATFORM=windows src/qt/test/test_bitcoin-qt # Windows
// QT_QPA_PLATFORM=cocoa src/qt/test/test_bitcoin-qt # macOS
-void TestGUI()
+void TestGUI(interfaces::Node& node)
{
// Set up wallet and chain with 105 blocks (5 mature blocks for spending).
TestChain100Setup test;
for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
}
- auto chain = interfaces::MakeChain();
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateMock());
+ node.context()->connman = std::move(test.m_node.connman);
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
{
@@ -161,10 +161,9 @@ void TestGUI()
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
SendCoinsDialog sendCoinsDialog(platformStyle.get());
TransactionView transactionView(platformStyle.get());
- auto node = interfaces::MakeNode();
- OptionsModel optionsModel(*node);
+ OptionsModel optionsModel(node);
AddWallet(wallet);
- WalletModel walletModel(std::move(node->getWallets().back()), *node, platformStyle.get(), &optionsModel);
+ WalletModel walletModel(interfaces::MakeWallet(wallet), node, platformStyle.get(), &optionsModel);
RemoveWallet(wallet);
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);
@@ -262,5 +261,5 @@ void WalletTests::walletTests()
return;
}
#endif
- TestGUI();
+ TestGUI(m_node);
}
diff --git a/src/qt/test/wallettests.h b/src/qt/test/wallettests.h
index 342f7916c3..0a7b57a678 100644
--- a/src/qt/test/wallettests.h
+++ b/src/qt/test/wallettests.h
@@ -4,8 +4,16 @@
#include <QObject>
#include <QTest>
+namespace interfaces {
+class Node;
+} // namespace interfaces
+
class WalletTests : public QObject
{
+ public:
+ WalletTests(interfaces::Node& node) : m_node(node) {}
+ interfaces::Node& m_node;
+
Q_OBJECT
private Q_SLOTS:
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index fac6bcd60d..747113fbb4 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2289,3 +2289,5 @@ void RegisterBlockchainRPCCommands(CRPCTable &t)
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
+
+NodeContext* g_rpc_node = nullptr;
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index ff461fbcbc..8a1264f824 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -17,6 +17,7 @@ class CBlock;
class CBlockIndex;
class CTxMemPool;
class UniValue;
+struct NodeContext;
static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
@@ -46,4 +47,9 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
/** Used by getblockstats to get feerates at different percentiles by weight */
void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);
+//! Pointer to node state that needs to be declared as a global to be accessible
+//! RPC methods. Due to limitations of the RPC framework, there's currently no
+//! direct way to pass in state to RPC methods without globals.
+extern NodeContext* g_rpc_node;
+
#endif
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 07c2958635..bfa3e35d96 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -13,6 +13,7 @@
#include <key_io.h>
#include <miner.h>
#include <net.h>
+#include <node/context.h>
#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
@@ -424,10 +425,10 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
+ if (g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
if (::ChainstateActive().IsInitialBlockDownload())
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 7b1507e4dc..f443f37c6d 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -11,7 +11,9 @@
#include <net_processing.h>
#include <net_permissions.h>
#include <netbase.h>
+#include <node/context.h>
#include <policy/settings.h>
+#include <rpc/blockchain.h>
#include <rpc/protocol.h>
#include <rpc/util.h>
#include <sync.h>
@@ -38,10 +40,10 @@ static UniValue getconnectioncount(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
+ return (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
}
static UniValue ping(const JSONRPCRequest& request)
@@ -58,11 +60,11 @@ static UniValue ping(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
// Request that each node send a ping during next message processing pass
- g_connman->ForEachNode([](CNode* pnode) {
+ g_rpc_node->connman->ForEachNode([](CNode* pnode) {
pnode->fPingQueued = true;
});
return NullUniValue;
@@ -131,11 +133,11 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
std::vector<CNodeStats> vstats;
- g_connman->GetNodeStats(vstats);
+ g_rpc_node->connman->GetNodeStats(vstats);
UniValue ret(UniValue::VARR);
@@ -234,7 +236,7 @@ static UniValue addnode(const JSONRPCRequest& request)
},
}.ToString());
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
std::string strNode = request.params[0].get_str();
@@ -242,18 +244,18 @@ static UniValue addnode(const JSONRPCRequest& request)
if (strCommand == "onetry")
{
CAddress addr;
- g_connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true);
+ g_rpc_node->connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true);
return NullUniValue;
}
if (strCommand == "add")
{
- if(!g_connman->AddNode(strNode))
+ if(!g_rpc_node->connman->AddNode(strNode))
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
}
else if(strCommand == "remove")
{
- if(!g_connman->RemoveAddedNode(strNode))
+ if(!g_rpc_node->connman->RemoveAddedNode(strNode))
throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
}
@@ -279,7 +281,7 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
bool success;
@@ -288,11 +290,11 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
if (!address_arg.isNull() && id_arg.isNull()) {
/* handle disconnect-by-address */
- success = g_connman->DisconnectNode(address_arg.get_str());
+ success = g_rpc_node->connman->DisconnectNode(address_arg.get_str());
} else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
/* handle disconnect-by-id */
NodeId nodeid = (NodeId) id_arg.get_int64();
- success = g_connman->DisconnectNode(nodeid);
+ success = g_rpc_node->connman->DisconnectNode(nodeid);
} else {
throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
}
@@ -333,10 +335,10 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- std::vector<AddedNodeInfo> vInfo = g_connman->GetAddedNodeInfo();
+ std::vector<AddedNodeInfo> vInfo = g_rpc_node->connman->GetAddedNodeInfo();
if (!request.params[0].isNull()) {
bool found = false;
@@ -399,21 +401,21 @@ static UniValue getnettotals(const JSONRPCRequest& request)
+ HelpExampleRpc("getnettotals", "")
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
UniValue obj(UniValue::VOBJ);
- obj.pushKV("totalbytesrecv", g_connman->GetTotalBytesRecv());
- obj.pushKV("totalbytessent", g_connman->GetTotalBytesSent());
+ obj.pushKV("totalbytesrecv", g_rpc_node->connman->GetTotalBytesRecv());
+ obj.pushKV("totalbytessent", g_rpc_node->connman->GetTotalBytesSent());
obj.pushKV("timemillis", GetTimeMillis());
UniValue outboundLimit(UniValue::VOBJ);
- outboundLimit.pushKV("timeframe", g_connman->GetMaxOutboundTimeframe());
- outboundLimit.pushKV("target", g_connman->GetMaxOutboundTarget());
- outboundLimit.pushKV("target_reached", g_connman->OutboundTargetReached(false));
- outboundLimit.pushKV("serve_historical_blocks", !g_connman->OutboundTargetReached(true));
- outboundLimit.pushKV("bytes_left_in_cycle", g_connman->GetOutboundTargetBytesLeft());
- outboundLimit.pushKV("time_left_in_cycle", g_connman->GetMaxOutboundTimeLeftInCycle());
+ outboundLimit.pushKV("timeframe", g_rpc_node->connman->GetMaxOutboundTimeframe());
+ outboundLimit.pushKV("target", g_rpc_node->connman->GetMaxOutboundTarget());
+ outboundLimit.pushKV("target_reached", g_rpc_node->connman->OutboundTargetReached(false));
+ outboundLimit.pushKV("serve_historical_blocks", !g_rpc_node->connman->OutboundTargetReached(true));
+ outboundLimit.pushKV("bytes_left_in_cycle", g_rpc_node->connman->GetOutboundTargetBytesLeft());
+ outboundLimit.pushKV("time_left_in_cycle", g_rpc_node->connman->GetMaxOutboundTimeLeftInCycle());
obj.pushKV("uploadtarget", outboundLimit);
return obj;
}
@@ -492,16 +494,16 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
obj.pushKV("version", CLIENT_VERSION);
obj.pushKV("subversion", strSubVersion);
obj.pushKV("protocolversion",PROTOCOL_VERSION);
- if (g_connman) {
- ServiceFlags services = g_connman->GetLocalServices();
+ if (g_rpc_node->connman) {
+ ServiceFlags services = g_rpc_node->connman->GetLocalServices();
obj.pushKV("localservices", strprintf("%016x", services));
obj.pushKV("localservicesnames", GetServicesNames(services));
}
obj.pushKV("localrelay", g_relay_txes);
obj.pushKV("timeoffset", GetTimeOffset());
- if (g_connman) {
- obj.pushKV("networkactive", g_connman->GetNetworkActive());
- obj.pushKV("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
+ if (g_rpc_node->connman) {
+ obj.pushKV("networkactive", g_rpc_node->connman->GetNetworkActive());
+ obj.pushKV("connections", (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
}
obj.pushKV("networks", GetNetworksInfo());
obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
@@ -546,7 +548,7 @@ static UniValue setban(const JSONRPCRequest& request)
if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
throw std::runtime_error(help.ToString());
}
- if (!g_banman) {
+ if (!g_rpc_node->banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
}
@@ -570,7 +572,7 @@ static UniValue setban(const JSONRPCRequest& request)
if (strCommand == "add")
{
- if (isSubnet ? g_banman->IsBanned(subNet) : g_banman->IsBanned(netAddr)) {
+ if (isSubnet ? g_rpc_node->banman->IsBanned(subNet) : g_rpc_node->banman->IsBanned(netAddr)) {
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
}
@@ -583,20 +585,20 @@ static UniValue setban(const JSONRPCRequest& request)
absolute = true;
if (isSubnet) {
- g_banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute);
- if (g_connman) {
- g_connman->DisconnectNode(subNet);
+ g_rpc_node->banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute);
+ if (g_rpc_node->connman) {
+ g_rpc_node->connman->DisconnectNode(subNet);
}
} else {
- g_banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
- if (g_connman) {
- g_connman->DisconnectNode(netAddr);
+ g_rpc_node->banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
+ if (g_rpc_node->connman) {
+ g_rpc_node->connman->DisconnectNode(netAddr);
}
}
}
else if(strCommand == "remove")
{
- if (!( isSubnet ? g_banman->Unban(subNet) : g_banman->Unban(netAddr) )) {
+ if (!( isSubnet ? g_rpc_node->banman->Unban(subNet) : g_rpc_node->banman->Unban(netAddr) )) {
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned.");
}
}
@@ -615,12 +617,12 @@ static UniValue listbanned(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_banman) {
+ if(!g_rpc_node->banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
}
banmap_t banMap;
- g_banman->GetBanned(banMap);
+ g_rpc_node->banman->GetBanned(banMap);
UniValue bannedAddresses(UniValue::VARR);
for (const auto& entry : banMap)
@@ -649,11 +651,11 @@ static UniValue clearbanned(const JSONRPCRequest& request)
+ HelpExampleRpc("clearbanned", "")
},
}.Check(request);
- if (!g_banman) {
+ if (!g_rpc_node->banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
}
- g_banman->ClearBanned();
+ g_rpc_node->banman->ClearBanned();
return NullUniValue;
}
@@ -669,13 +671,13 @@ static UniValue setnetworkactive(const JSONRPCRequest& request)
RPCExamples{""},
}.Check(request);
- if (!g_connman) {
+ if (!g_rpc_node->connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
}
- g_connman->SetNetworkActive(request.params[0].get_bool());
+ g_rpc_node->connman->SetNetworkActive(request.params[0].get_bool());
- return g_connman->GetNetworkActive();
+ return g_rpc_node->connman->GetNetworkActive();
}
static UniValue getnodeaddresses(const JSONRPCRequest& request)
@@ -701,7 +703,7 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
+ HelpExampleRpc("getnodeaddresses", "8")
},
}.Check(request);
- if (!g_connman) {
+ if (!g_rpc_node->connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
}
@@ -713,7 +715,7 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
}
}
// returns a shuffled list of CAddress
- std::vector<CAddress> vAddr = g_connman->GetAddresses();
+ std::vector<CAddress> vAddr = g_rpc_node->connman->GetAddresses();
UniValue ret(UniValue::VARR);
int address_return_count = std::min<int>(count, vAddr.size());
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 487f74c3e1..74cd46080b 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -11,6 +11,7 @@
#include <key_io.h>
#include <merkleblock.h>
#include <node/coin.h>
+#include <node/context.h>
#include <node/psbt.h>
#include <node/transaction.h>
#include <policy/policy.h>
@@ -18,6 +19,7 @@
#include <primitives/transaction.h>
#include <psbt.h>
#include <random.h>
+#include <rpc/blockchain.h>
#include <rpc/rawtransaction_util.h>
#include <rpc/server.h>
#include <rpc/util.h>
@@ -817,7 +819,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
std::string err_string;
AssertLockNotHeld(cs_main);
- const TransactionError err = BroadcastTransaction(tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
+ const TransactionError err = BroadcastTransaction(*g_rpc_node, tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
if (TransactionError::OK != err) {
throw JSONRPCTransactionError(err, err_string);
}
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index adda90c104..653b287e97 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -13,8 +13,6 @@
#include <tuple>
-InitInterfaces* g_rpc_interfaces = nullptr;
-
void RPCTypeCheck(const UniValue& params,
const std::list<UniValueType>& typesExpected,
bool fAllowNull)
diff --git a/src/rpc/util.h b/src/rpc/util.h
index ec36956c95..221638aa9e 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -25,12 +25,6 @@
class FillableSigningProvider;
class CPubKey;
class CScript;
-struct InitInterfaces;
-
-//! Pointers to interfaces that need to be accessible from RPC methods. Due to
-//! limitations of the RPC framework, there's currently no direct way to pass in
-//! state to RPC method implementations.
-extern InitInterfaces* g_rpc_interfaces;
/** Wrapper for UniValue::VType, which includes typeAny:
* Used to denote don't care type. */
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 5ae0812243..faff1931cd 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -7,8 +7,8 @@
#include <rpc/util.h>
#include <core_io.h>
-#include <init.h>
#include <interfaces/chain.h>
+#include <node/context.h>
#include <test/setup_common.h>
#include <util/time.h>
@@ -112,14 +112,14 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
std::string notsigned = r.get_str();
std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
- InitInterfaces interfaces;
- interfaces.chain = interfaces::MakeChain();
- g_rpc_interfaces = &interfaces;
+ NodeContext node;
+ node.chain = interfaces::MakeChain(node);
+ g_rpc_node = &node;
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
- g_rpc_interfaces = nullptr;
+ g_rpc_node = nullptr;
}
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
diff --git a/src/test/setup_common.cpp b/src/test/setup_common.cpp
index bbdf1ef830..89a19e172d 100644
--- a/src/test/setup_common.cpp
+++ b/src/test/setup_common.cpp
@@ -15,6 +15,7 @@
#include <net.h>
#include <noui.h>
#include <pow.h>
+#include <rpc/blockchain.h>
#include <rpc/register.h>
#include <rpc/server.h>
#include <script/sigcache.h>
@@ -76,6 +77,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
const CChainParams& chainparams = Params();
// Ideally we'd move all the RPC tests to the functional testing framework
// instead of unit tests, but for now we need these here.
+ g_rpc_node = &m_node;
RegisterAllCoreRPCCommands(tableRPC);
// We have to run a scheduler thread to prevent ActivateBestChain
@@ -104,8 +106,8 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
for (int i = 0; i < nScriptCheckThreads - 1; i++)
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
- g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- g_connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
+ m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
}
TestingSetup::~TestingSetup()
@@ -114,8 +116,9 @@ TestingSetup::~TestingSetup()
threadGroup.join_all();
GetMainSignals().FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler();
- g_connman.reset();
- g_banman.reset();
+ g_rpc_node = nullptr;
+ m_node.connman.reset();
+ m_node.banman.reset();
UnloadBlockIndex();
g_chainstate.reset();
pblocktree.reset();
diff --git a/src/test/setup_common.h b/src/test/setup_common.h
index 6c9494898c..5731b50e31 100644
--- a/src/test/setup_common.h
+++ b/src/test/setup_common.h
@@ -8,6 +8,7 @@
#include <chainparamsbase.h>
#include <fs.h>
#include <key.h>
+#include <node/context.h>
#include <pubkey.h>
#include <random.h>
#include <scheduler.h>
@@ -67,6 +68,7 @@ private:
* Included are coins database, script check threads setup.
*/
struct TestingSetup : public BasicTestingSetup {
+ NodeContext m_node;
boost::thread_group threadGroup;
CScheduler scheduler;
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 34192c6b6a..10e5949d54 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -706,7 +706,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
BOOST_CHECK_EQUAL(nDustThreshold, 546);
// dust:
t.vout[0].nValue = nDustThreshold - 1;
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "dust");
// not dust:
t.vout[0].nValue = nDustThreshold;
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
@@ -716,14 +718,18 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
dustRelayFee = CFeeRate(3702);
// dust:
t.vout[0].nValue = 673 - 1;
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "dust");
// not dust:
t.vout[0].nValue = 673;
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
t.vout[0].scriptPubKey = CScript() << OP_1;
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "scriptpubkey");
// MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
@@ -733,7 +739,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
// MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "scriptpubkey");
// Data payload can be encoded in any way...
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("");
@@ -748,7 +756,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
// ...so long as it only contains PUSHDATA's
t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN;
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "scriptpubkey");
// TX_NULL_DATA w/o PUSHDATA
t.vout.resize(1);
@@ -759,15 +769,21 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
t.vout.resize(2);
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "multi-op-return");
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "multi-op-return");
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
+ reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK_EQUAL(reason, "multi-op-return");
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index 1e7d24c71c..46042f5634 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -138,7 +138,7 @@ std::string EncodeBase64(const unsigned char* pch, size_t len)
std::string EncodeBase64(const std::string& str)
{
- return EncodeBase64((const unsigned char*)str.c_str(), str.size());
+ return EncodeBase64((const unsigned char*)str.data(), str.size());
}
std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
@@ -207,7 +207,7 @@ std::string EncodeBase32(const unsigned char* pch, size_t len)
std::string EncodeBase32(const std::string& str)
{
- return EncodeBase32((const unsigned char*)str.c_str(), str.size());
+ return EncodeBase32((const unsigned char*)str.data(), str.size());
}
std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index f6179aa298..b50f00e7d1 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -23,7 +23,7 @@ int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, cons
unsigned char buf[CSHA512::OUTPUT_SIZE];
CSHA512 di;
- di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size());
+ di.Write((const unsigned char*)strKeyData.data(), strKeyData.size());
di.Write(chSalt.data(), chSalt.size());
di.Finalize(buf);
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 3657a157b6..a8b3df1f2e 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -6,6 +6,7 @@
#include <init.h>
#include <interfaces/chain.h>
#include <net.h>
+#include <node/context.h>
#include <outputtype.h>
#include <util/moneystr.h>
#include <util/system.h>
@@ -25,8 +26,8 @@ public:
//! Wallets parameter interaction
bool ParameterInteraction() const override;
- //! Add wallets that should be opened to list of init interfaces.
- void Construct(InitInterfaces& interfaces) const override;
+ //! Add wallets that should be opened to list of chain clients.
+ void Construct(NodeContext& node) const override;
};
const WalletInitInterface& g_wallet_init_interface = WalletInit();
@@ -125,12 +126,12 @@ bool WalletInit::ParameterInteraction() const
return true;
}
-void WalletInit::Construct(InitInterfaces& interfaces) const
+void WalletInit::Construct(NodeContext& node) const
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
LogPrintf("Wallet disabled!\n");
return;
}
gArgs.SoftSetArg("-wallet", "");
- interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient(*interfaces.chain, gArgs.GetArgs("-wallet")));
+ node.chain_clients.emplace_back(interfaces::MakeWalletClient(*node.chain, gArgs.GetArgs("-wallet")));
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 7701767bc2..bfa4cf2bbe 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -5,9 +5,9 @@
#include <amount.h>
#include <core_io.h>
-#include <init.h>
#include <interfaces/chain.h>
#include <key_io.h>
+#include <node/context.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
@@ -2587,7 +2587,7 @@ static UniValue loadwallet(const JSONRPCRequest& request)
std::string error;
std::vector<std::string> warning;
- std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning);
+ std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_chain, location, error, warning);
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error);
UniValue obj(UniValue::VOBJ);
@@ -2713,7 +2713,7 @@ static UniValue createwallet(const JSONRPCRequest& request)
std::string error;
std::shared_ptr<CWallet> wallet;
- WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet);
+ WalletCreationStatus status = CreateWallet(*g_rpc_chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet);
switch (status) {
case WalletCreationStatus::CREATION_FAILED:
throw JSONRPCError(RPC_WALLET_ERROR, error);
@@ -4255,3 +4255,5 @@ void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
handlers.emplace_back(chain.handleRpc(commands[vcidx]));
}
+
+interfaces::Chain* g_rpc_chain = nullptr;
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 1c0523c90b..31d3f7a5f9 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -21,6 +21,12 @@ class Chain;
class Handler;
}
+//! Pointer to chain interface that needs to be declared as a global to be
+//! accessible loadwallet and createwallet methods. Due to limitations of the
+//! RPC framework, there's currently no direct way to pass in state to RPC
+//! methods without globals.
+extern interfaces::Chain* g_rpc_chain;
+
void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique_ptr<interfaces::Handler>>& handlers);
/**
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 9e7f0ed773..397e6ea9d3 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <node/context.h>
#include <wallet/wallet.h>
#include <wallet/coinselection.h>
#include <wallet/coincontrol.h>
@@ -28,7 +29,8 @@ std::vector<std::unique_ptr<CWalletTx>> wtxn;
typedef std::set<CInputCoin> CoinSet;
static std::vector<COutput> vCoins;
-static auto testChain = interfaces::MakeChain();
+static NodeContext testNode;
+static auto testChain = interfaces::MakeChain(testNode);
static CWallet testWallet(testChain.get(), WalletLocation(), WalletDatabase::CreateDummy());
static CAmount balance = 0;
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index e2b7075085..eb4e72c88b 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -6,6 +6,7 @@
#define BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
#include <interfaces/chain.h>
+#include <node/context.h>
#include <test/setup_common.h>
@@ -17,7 +18,8 @@ struct InitWalletDirTestingSetup: public BasicTestingSetup {
fs::path m_datadir;
fs::path m_cwd;
std::map<std::string, fs::path> m_walletdir_path_cases;
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ NodeContext m_node;
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::ChainClient> m_chain_client;
};
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
index 12355e300a..24636fd599 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key.h>
+#include <node/context.h>
#include <script/script.h>
#include <script/standard.h>
#include <test/setup_common.h>
@@ -26,7 +27,8 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
CKey uncompressedKey;
uncompressedKey.MakeNewKey(false);
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain();
+ NodeContext node;
+ std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
CScript scriptPubKey;
isminetype result;
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index c1dbecdf8c..def6f1934e 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -9,6 +9,7 @@
#include <interfaces/chain.h>
#include <interfaces/wallet.h>
+#include <node/context.h>
#include <wallet/wallet.h>
#include <memory>
@@ -18,7 +19,8 @@
struct WalletTestingSetup: public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ NodeContext m_node;
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::ChainClient> m_chain_client = interfaces::MakeWalletClient(*m_chain, {});
CWallet m_wallet;
};
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index ca4b932915..72e1b4e83b 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -9,6 +9,7 @@
#include <vector>
#include <interfaces/chain.h>
+#include <node/context.h>
#include <policy/policy.h>
#include <rpc/server.h>
#include <test/setup_common.h>
@@ -41,7 +42,8 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- auto chain = interfaces::MakeChain();
+ NodeContext node;
+ auto chain = interfaces::MakeChain(node);
auto locked_chain = chain->lock();
LockAssertion lock(::cs_main);
@@ -120,7 +122,8 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- auto chain = interfaces::MakeChain();
+ NodeContext node;
+ auto chain = interfaces::MakeChain(node);
auto locked_chain = chain->lock();
LockAssertion lock(::cs_main);
@@ -187,7 +190,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
- auto chain = interfaces::MakeChain();
+ NodeContext node;
+ auto chain = interfaces::MakeChain(node);
auto locked_chain = chain->lock();
LockAssertion lock(::cs_main);
@@ -243,7 +247,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- auto chain = interfaces::MakeChain();
+ NodeContext node;
+ auto chain = interfaces::MakeChain(node);
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
auto spk_man = wallet.GetLegacyScriptPubKeyMan();
@@ -474,7 +479,8 @@ public:
return it->second;
}
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ NodeContext m_node;
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<CWallet> wallet;
};
@@ -546,7 +552,8 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
- auto chain = interfaces::MakeChain();
+ NodeContext node;
+ auto chain = interfaces::MakeChain(node);
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
diff --git a/src/walletinitinterface.h b/src/walletinitinterface.h
index 2e1fdf4f3a..7ccda1c566 100644
--- a/src/walletinitinterface.h
+++ b/src/walletinitinterface.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_WALLETINITINTERFACE_H
#define BITCOIN_WALLETINITINTERFACE_H
-struct InitInterfaces;
+struct NodeContext;
class WalletInitInterface {
public:
@@ -15,8 +15,8 @@ public:
virtual void AddWalletOptions() const = 0;
/** Check wallet parameter interaction */
virtual bool ParameterInteraction() const = 0;
- /** Add wallets that should be opened to list of init interfaces. */
- virtual void Construct(InitInterfaces& interfaces) const = 0;
+ /** Add wallets that should be opened to list of chain clients. */
+ virtual void Construct(NodeContext& node) const = 0;
virtual ~WalletInitInterface() {}
};