0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-03-05 14:06:27 -05:00

Merge #16839: Replace Connman and BanMan globals with NodeContext local

362ded410b Avoid using g_rpc_node global in wallet code (Russell Yanofsky)
8922d7f6b7 scripted-diff: Remove g_connman, g_banman globals (Russell Yanofsky)
e6f4f895d5 Pass NodeContext, ConnMan, BanMan references more places (Russell Yanofsky)
4d5448c76b MOVEONLY: Move NodeContext struct to node/context.h (Russell Yanofsky)
301bd41a2e scripted-diff: Rename InitInterfaces to NodeContext (Russell Yanofsky)

Pull request description:

  This change is mainly a naming / organization change intended to simplify #10102. It:

  - Renames struct InitInterfaces to struct NodeContext and moves it from
    src/init.h to src/node/context.h. This is a cosmetic change intended to make
    the point of the struct more obvious.

  - Gets rid of BanMan and ConnMan globals making them NodeContext members
    instead. Getting rid of these globals has been talked about in past as a way
    to implement testing and simulations. Making them NodeContext members is a
    way of keeping them accessible without the globals.

  - Splits g_rpc_interfaces global into g_rpc_node and g_rpc_chain globals. This
    better separates node and wallet rpc methods. Node RPC methods should have
    access NodeContext, while wallet RPC methods should only have indirect access
    to node functionality via interfaces::Chain.

  - Adds NodeContext& references to interfaces::Chain class and the
    interfaces::MakeChain() function. This is needed to access ConnMan and BanMan
    instances without the globals.

  - Gets rid of redundant Node and Chain instances in Qt tests. This is
    needed due to the previous MakeChain change, and also makes test setup a
    little more straightforward. More cleanup could be done in the future, but it
    will require deduplication of bitcoind, bitcoin-qt, and TestingSetup init
    code.

ACKs for top commit:
  laanwj:
    ACK 362ded410b

Tree-SHA512: 9ae6ff1e33423291d1e52056bac95e0874538390892a6e83c4c115b3c73155a8827c0191b46eb3d14e3b3f6c23ccb08095490880fbc3188026319c71739f7db2
This commit is contained in:
Wladimir J. van der Laan 2019-10-30 12:25:26 +01:00
commit 471e5f8829
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
45 changed files with 336 additions and 211 deletions

View file

@ -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 \

View file

@ -66,5 +66,4 @@ private:
const int64_t m_default_ban_time;
};
extern std::unique_ptr<BanMan> g_banman;
#endif

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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); }

View file

@ -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();

View file

@ -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())

13
src/node/context.cpp Normal file
View file

@ -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() {}

44
src/node/context.h Normal file
View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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:

View file

@ -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]");

View file

@ -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:

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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:

View file

@ -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;

View file

@ -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

View file

@ -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())

View file

@ -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());

View file

@ -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);
}

View file

@ -13,8 +13,6 @@
#include <tuple>
InitInterfaces* g_rpc_interfaces = nullptr;
void RPCTypeCheck(const UniValue& params,
const std::list<UniValueType>& typesExpected,
bool fAllowNull)

View file

@ -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. */

View file

@ -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)

View file

@ -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();

View file

@ -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;

View file

@ -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")));
}

View file

@ -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;

View file

@ -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);
/**

View file

@ -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;

View file

@ -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;
};

View file

@ -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;

View file

@ -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;
};

View file

@ -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);

View file

@ -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() {}
};