Line data Source code
1 : // Copyright (c) 2018-2020 The Bitcoin Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include <interfaces/node.h> 6 : 7 : #include <addrdb.h> 8 : #include <banman.h> 9 : #include <chain.h> 10 : #include <chainparams.h> 11 : #include <init.h> 12 : #include <interfaces/chain.h> 13 : #include <interfaces/handler.h> 14 : #include <interfaces/wallet.h> 15 : #include <net.h> 16 : #include <net_processing.h> 17 : #include <netaddress.h> 18 : #include <netbase.h> 19 : #include <node/context.h> 20 : #include <node/ui_interface.h> 21 : #include <policy/feerate.h> 22 : #include <policy/fees.h> 23 : #include <policy/settings.h> 24 : #include <primitives/block.h> 25 : #include <rpc/server.h> 26 : #include <shutdown.h> 27 : #include <support/allocators/secure.h> 28 : #include <sync.h> 29 : #include <txmempool.h> 30 : #include <util/check.h> 31 : #include <util/ref.h> 32 : #include <util/system.h> 33 : #include <util/translation.h> 34 : #include <validation.h> 35 : #include <warnings.h> 36 : 37 : #if defined(HAVE_CONFIG_H) 38 : #include <config/bitcoin-config.h> 39 : #endif 40 : 41 : #include <univalue.h> 42 : 43 : #include <boost/signals2/signal.hpp> 44 : 45 : namespace interfaces { 46 : namespace { 47 : 48 3 : class NodeImpl : public Node 49 : { 50 : public: 51 2 : NodeImpl(NodeContext* context) { setContext(context); } 52 0 : void initLogging() override { InitLogging(*Assert(m_context->args)); } 53 0 : void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); } 54 0 : bilingual_str getWarnings() override { return GetWarnings(true); } 55 0 : uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); } 56 0 : bool baseInitialize() override 57 : { 58 0 : return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs) && AppInitSanityChecks() && 59 0 : AppInitLockDataDirectory() && AppInitInterfaces(*m_context); 60 : } 61 0 : bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override 62 : { 63 0 : return AppInitMain(m_context_ref, *m_context, tip_info); 64 : } 65 0 : void appShutdown() override 66 : { 67 0 : Interrupt(*m_context); 68 0 : Shutdown(*m_context); 69 0 : } 70 0 : void startShutdown() override 71 : { 72 0 : StartShutdown(); 73 : // Stop RPC for clean shutdown if any of waitfor* commands is executed. 74 0 : if (gArgs.GetBoolArg("-server", false)) { 75 0 : InterruptRPC(); 76 0 : StopRPC(); 77 0 : } 78 0 : } 79 0 : bool shutdownRequested() override { return ShutdownRequested(); } 80 0 : void mapPort(bool use_upnp) override 81 : { 82 0 : if (use_upnp) { 83 0 : StartMapPort(); 84 0 : } else { 85 0 : InterruptMapPort(); 86 0 : StopMapPort(); 87 : } 88 0 : } 89 0 : bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); } 90 0 : size_t getNodeCount(CConnman::NumConnections flags) override 91 : { 92 0 : return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0; 93 : } 94 0 : bool getNodesStats(NodesStats& stats) override 95 : { 96 0 : stats.clear(); 97 : 98 0 : if (m_context->connman) { 99 0 : std::vector<CNodeStats> stats_temp; 100 0 : m_context->connman->GetNodeStats(stats_temp); 101 : 102 0 : stats.reserve(stats_temp.size()); 103 0 : for (auto& node_stats_temp : stats_temp) { 104 0 : stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats()); 105 : } 106 : 107 : // Try to retrieve the CNodeStateStats for each node. 108 0 : TRY_LOCK(::cs_main, lockMain); 109 0 : if (lockMain) { 110 0 : for (auto& node_stats : stats) { 111 0 : std::get<1>(node_stats) = 112 0 : GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats)); 113 : } 114 0 : } 115 : return true; 116 0 : } 117 0 : return false; 118 0 : } 119 0 : bool getBanned(banmap_t& banmap) override 120 : { 121 0 : if (m_context->banman) { 122 0 : m_context->banman->GetBanned(banmap); 123 0 : return true; 124 : } 125 0 : return false; 126 0 : } 127 0 : bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override 128 : { 129 0 : if (m_context->banman) { 130 0 : m_context->banman->Ban(net_addr, ban_time_offset); 131 0 : return true; 132 : } 133 0 : return false; 134 0 : } 135 0 : bool unban(const CSubNet& ip) override 136 : { 137 0 : if (m_context->banman) { 138 0 : m_context->banman->Unban(ip); 139 0 : return true; 140 : } 141 0 : return false; 142 0 : } 143 0 : bool disconnectByAddress(const CNetAddr& net_addr) override 144 : { 145 0 : if (m_context->connman) { 146 0 : return m_context->connman->DisconnectNode(net_addr); 147 : } 148 0 : return false; 149 0 : } 150 0 : bool disconnectById(NodeId id) override 151 : { 152 0 : if (m_context->connman) { 153 0 : return m_context->connman->DisconnectNode(id); 154 : } 155 0 : return false; 156 0 : } 157 0 : int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; } 158 0 : int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; } 159 0 : size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; } 160 0 : size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; } 161 0 : bool getHeaderTip(int& height, int64_t& block_time) override 162 : { 163 0 : LOCK(::cs_main); 164 0 : if (::pindexBestHeader) { 165 0 : height = ::pindexBestHeader->nHeight; 166 0 : block_time = ::pindexBestHeader->GetBlockTime(); 167 0 : return true; 168 : } 169 0 : return false; 170 0 : } 171 0 : int getNumBlocks() override 172 : { 173 0 : LOCK(::cs_main); 174 0 : return ::ChainActive().Height(); 175 0 : } 176 0 : uint256 getBestBlockHash() override 177 : { 178 0 : const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip()); 179 0 : return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash(); 180 0 : } 181 0 : int64_t getLastBlockTime() override 182 : { 183 0 : LOCK(::cs_main); 184 0 : if (::ChainActive().Tip()) { 185 0 : return ::ChainActive().Tip()->GetBlockTime(); 186 : } 187 0 : return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network 188 0 : } 189 0 : double getVerificationProgress() override 190 : { 191 : const CBlockIndex* tip; 192 : { 193 0 : LOCK(::cs_main); 194 0 : tip = ::ChainActive().Tip(); 195 0 : } 196 0 : return GuessVerificationProgress(Params().TxData(), tip); 197 0 : } 198 0 : bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } 199 0 : bool getReindex() override { return ::fReindex; } 200 0 : bool getImporting() override { return ::fImporting; } 201 0 : void setNetworkActive(bool active) override 202 : { 203 0 : if (m_context->connman) { 204 0 : m_context->connman->SetNetworkActive(active); 205 0 : } 206 0 : } 207 0 : bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); } 208 0 : CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override 209 : { 210 0 : FeeCalculation fee_calc; 211 0 : CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative); 212 0 : if (returned_target) { 213 0 : *returned_target = fee_calc.returnedTarget; 214 0 : } 215 : return result; 216 0 : } 217 0 : CFeeRate getDustRelayFee() override { return ::dustRelayFee; } 218 35 : UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override 219 : { 220 35 : JSONRPCRequest req(m_context_ref); 221 35 : req.params = params; 222 35 : req.strMethod = command; 223 35 : req.URI = uri; 224 35 : return ::tableRPC.execute(req); 225 35 : } 226 0 : std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); } 227 0 : void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); } 228 0 : void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); } 229 0 : bool getUnspentOutput(const COutPoint& output, Coin& coin) override 230 : { 231 0 : LOCK(::cs_main); 232 0 : return ::ChainstateActive().CoinsTip().GetCoin(output, coin); 233 0 : } 234 0 : WalletClient& walletClient() override 235 : { 236 0 : return *Assert(m_context->wallet_client); 237 : } 238 0 : std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override 239 : { 240 0 : return MakeHandler(::uiInterface.InitMessage_connect(fn)); 241 0 : } 242 0 : std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override 243 : { 244 0 : return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn)); 245 0 : } 246 0 : std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override 247 : { 248 0 : return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn)); 249 0 : } 250 0 : std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override 251 : { 252 0 : return MakeHandler(::uiInterface.ShowProgress_connect(fn)); 253 0 : } 254 0 : std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override 255 : { 256 0 : return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn)); 257 0 : } 258 0 : std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override 259 : { 260 0 : return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn)); 261 0 : } 262 0 : std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override 263 : { 264 0 : return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn)); 265 0 : } 266 0 : std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override 267 : { 268 0 : return MakeHandler(::uiInterface.BannedListChanged_connect(fn)); 269 0 : } 270 0 : std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override 271 : { 272 0 : return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { 273 0 : fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, 274 0 : GuessVerificationProgress(Params().TxData(), block)); 275 0 : })); 276 0 : } 277 0 : std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override 278 : { 279 0 : return MakeHandler( 280 0 : ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { 281 0 : fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, 282 : /* verification progress is unused when a header was received */ 0); 283 0 : })); 284 0 : } 285 1 : NodeContext* context() override { return m_context; } 286 1 : void setContext(NodeContext* context) override 287 : { 288 1 : m_context = context; 289 1 : if (context) { 290 1 : m_context_ref.Set(*context); 291 1 : } else { 292 0 : m_context_ref.Clear(); 293 : } 294 1 : } 295 1 : NodeContext* m_context{nullptr}; 296 : util::Ref m_context_ref; 297 : }; 298 : 299 : } // namespace 300 : 301 1 : std::unique_ptr<Node> MakeNode(NodeContext* context) { return MakeUnique<NodeImpl>(context); } 302 : 303 : } // namespace interfaces