mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
9924bce317[gui] intro: enable pruning by default unless disk is big (Sjors Provoost)c8de347a9d[gui] intro: add prune preference (Sjors Provoost)1bbc49d207[gui] intro: inform caller if intro was shown (Sjors Provoost)1957103786[gui] add explicit prune setter (Sjors Provoost)1bccf6a52d[node] add forceSetArg to interface (Sjors Provoost) Pull request description: This adds a checkbox to the intro screen to enable pruning from the get go. If the user has plenty of space, it's unchecked by default: <img width="671" alt="big" src="https://user-images.githubusercontent.com/10217/63641289-10339000-c6ac-11e9-98d7-caf64dff0da6.png"> If the user has insufficient space it's checked by default: <img width="897" alt="low" src="https://user-images.githubusercontent.com/10217/63641276-d4002f80-c6ab-11e9-9f5b-a53472f814ff.png"> When the user has barely enough space and is likely to need pruning in the near future, this is shown in yellow and we also check the prune box: <img width="662" alt="medium" src="https://user-images.githubusercontent.com/10217/63641294-1c1f5200-c6ac-11e9-8ecb-6b69e42b1ece.png"> The cut-off for this 10 GB above `m_assumed_blockchain_size` (`=240` in `chainparams.cpp`). If the user launches the first time with `-prune=...` then we disable the check box and display the correct size (rounded to GB): <img width="658" alt="Schermafbeelding 2019-08-24 om 20 23 14" src="https://user-images.githubusercontent.com/10217/63641351-09594d00-c6ad-11e9-94fe-fe5ed562e109.png"> The 2 GB default matches the settings default. The user can't change it in the intro screen, but can change it later. I'm tempted to increase that default to 10 GB, and then have the intro screen reduce it if space is really tight. Tips for testing: * move your existing data dir elsewhere * wipe data dir at every restart (behavior is different if it exists) * launch with `bitcoin-qt -resetguisettings -lang=en` (there's some space issues in different languages) * fake your free space by changing `intro.cpp` line 90: `freeBytesAvailable = 5000000000; // 5 GB` * try both testnet and mainnet, because settings are seperate. In particular note how step 7 in `GuiMain` switches where `QTSettings settings` points to; this had me thoroughly confused on testnet, because I was setting them too early. ACKs for top commit: jonasschnelli: Tested ACK9924bce317ryanofsky: utACK9924bce317. The changes are very logical, and implement the feature in a clean that way that doesn't add a lot of complication and shouldn't interfere with future improvements. I looked at Luke's branch too, and I think there's also a lot of great stuff there that seems fully compatible with this change. Tree-SHA512: 9523961451c53aebd347716976bc3a4a398f989dc21e9bbbd357060bd11a8f46c435f068bd421bb31ccb08e55445ef67bc347d8d19a4fb8fde9d6d3f9a3bcbb0
329 lines
12 KiB
C++
329 lines
12 KiB
C++
// Copyright (c) 2018 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <interfaces/node.h>
|
|
|
|
#include <addrdb.h>
|
|
#include <amount.h>
|
|
#include <banman.h>
|
|
#include <chain.h>
|
|
#include <chainparams.h>
|
|
#include <init.h>
|
|
#include <interfaces/chain.h>
|
|
#include <interfaces/handler.h>
|
|
#include <interfaces/wallet.h>
|
|
#include <net.h>
|
|
#include <net_processing.h>
|
|
#include <netaddress.h>
|
|
#include <netbase.h>
|
|
#include <policy/feerate.h>
|
|
#include <policy/fees.h>
|
|
#include <policy/policy.h>
|
|
#include <policy/settings.h>
|
|
#include <primitives/block.h>
|
|
#include <rpc/server.h>
|
|
#include <shutdown.h>
|
|
#include <support/allocators/secure.h>
|
|
#include <sync.h>
|
|
#include <txmempool.h>
|
|
#include <ui_interface.h>
|
|
#include <util/system.h>
|
|
#include <validation.h>
|
|
#include <warnings.h>
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include <config/bitcoin-config.h>
|
|
#endif
|
|
|
|
#include <atomic>
|
|
#include <univalue.h>
|
|
|
|
class CWallet;
|
|
fs::path GetWalletDir();
|
|
std::vector<fs::path> ListWalletDir();
|
|
std::vector<std::shared_ptr<CWallet>> GetWallets();
|
|
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning);
|
|
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result);
|
|
|
|
namespace interfaces {
|
|
|
|
class Wallet;
|
|
|
|
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
|
|
{
|
|
return gArgs.ParseParameters(argc, argv, error);
|
|
}
|
|
bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error, true); }
|
|
void forceSetArg(const std::string& arg, const std::string& value) override { gArgs.ForceSetArg(arg, value); }
|
|
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
|
|
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
|
|
void selectParams(const std::string& network) override { SelectParams(network); }
|
|
uint64_t getAssumedBlockchainSize() override { return Params().AssumedBlockchainSize(); }
|
|
uint64_t getAssumedChainStateSize() override { return Params().AssumedChainStateSize(); }
|
|
std::string getNetwork() override { return Params().NetworkIDString(); }
|
|
void initLogging() override { InitLogging(); }
|
|
void initParameterInteraction() override { InitParameterInteraction(); }
|
|
std::string getWarnings(const std::string& type) override { return GetWarnings(type); }
|
|
uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); }
|
|
bool baseInitialize() override
|
|
{
|
|
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
|
|
AppInitLockDataDirectory();
|
|
}
|
|
bool appInitMain() override { return AppInitMain(m_interfaces); }
|
|
void appShutdown() override
|
|
{
|
|
Interrupt();
|
|
Shutdown(m_interfaces);
|
|
}
|
|
void startShutdown() override { StartShutdown(); }
|
|
bool shutdownRequested() override { return ShutdownRequested(); }
|
|
void mapPort(bool use_upnp) override
|
|
{
|
|
if (use_upnp) {
|
|
StartMapPort();
|
|
} else {
|
|
InterruptMapPort();
|
|
StopMapPort();
|
|
}
|
|
}
|
|
void setupServerArgs() override { return SetupServerArgs(); }
|
|
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;
|
|
}
|
|
bool getNodesStats(NodesStats& stats) override
|
|
{
|
|
stats.clear();
|
|
|
|
if (g_connman) {
|
|
std::vector<CNodeStats> stats_temp;
|
|
g_connman->GetNodeStats(stats_temp);
|
|
|
|
stats.reserve(stats_temp.size());
|
|
for (auto& node_stats_temp : stats_temp) {
|
|
stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats());
|
|
}
|
|
|
|
// Try to retrieve the CNodeStateStats for each node.
|
|
TRY_LOCK(::cs_main, lockMain);
|
|
if (lockMain) {
|
|
for (auto& node_stats : stats) {
|
|
std::get<1>(node_stats) =
|
|
GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
bool getBanned(banmap_t& banmap) override
|
|
{
|
|
if (g_banman) {
|
|
g_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);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
bool unban(const CSubNet& ip) override
|
|
{
|
|
if (g_banman) {
|
|
g_banman->Unban(ip);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
bool disconnect(const CNetAddr& net_addr) override
|
|
{
|
|
if (g_connman) {
|
|
return g_connman->DisconnectNode(net_addr);
|
|
}
|
|
return false;
|
|
}
|
|
bool disconnect(NodeId id) override
|
|
{
|
|
if (g_connman) {
|
|
return g_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; }
|
|
size_t getMempoolSize() override { return ::mempool.size(); }
|
|
size_t getMempoolDynamicUsage() override { return ::mempool.DynamicMemoryUsage(); }
|
|
bool getHeaderTip(int& height, int64_t& block_time) override
|
|
{
|
|
LOCK(::cs_main);
|
|
if (::pindexBestHeader) {
|
|
height = ::pindexBestHeader->nHeight;
|
|
block_time = ::pindexBestHeader->GetBlockTime();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
int getNumBlocks() override
|
|
{
|
|
LOCK(::cs_main);
|
|
return ::ChainActive().Height();
|
|
}
|
|
int64_t getLastBlockTime() override
|
|
{
|
|
LOCK(::cs_main);
|
|
if (::ChainActive().Tip()) {
|
|
return ::ChainActive().Tip()->GetBlockTime();
|
|
}
|
|
return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
|
|
}
|
|
double getVerificationProgress() override
|
|
{
|
|
const CBlockIndex* tip;
|
|
{
|
|
LOCK(::cs_main);
|
|
tip = ::ChainActive().Tip();
|
|
}
|
|
return GuessVerificationProgress(Params().TxData(), tip);
|
|
}
|
|
bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
|
|
bool isAddressTypeSet() override { return !::gArgs.GetArg("-addresstype", "").empty(); }
|
|
bool getReindex() override { return ::fReindex; }
|
|
bool getImporting() override { return ::fImporting; }
|
|
void setNetworkActive(bool active) override
|
|
{
|
|
if (g_connman) {
|
|
g_connman->SetNetworkActive(active);
|
|
}
|
|
}
|
|
bool getNetworkActive() override { return g_connman && g_connman->GetNetworkActive(); }
|
|
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
|
|
{
|
|
FeeCalculation fee_calc;
|
|
CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative);
|
|
if (returned_target) {
|
|
*returned_target = fee_calc.returnedTarget;
|
|
}
|
|
return result;
|
|
}
|
|
CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
|
|
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
|
|
{
|
|
JSONRPCRequest req;
|
|
req.params = params;
|
|
req.strMethod = command;
|
|
req.URI = uri;
|
|
return ::tableRPC.execute(req);
|
|
}
|
|
std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
|
|
void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
|
|
void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
|
|
bool getUnspentOutput(const COutPoint& output, Coin& coin) override
|
|
{
|
|
LOCK(::cs_main);
|
|
return ::ChainstateActive().CoinsTip().GetCoin(output, coin);
|
|
}
|
|
std::string getWalletDir() override
|
|
{
|
|
return GetWalletDir().string();
|
|
}
|
|
std::vector<std::string> listWalletDir() override
|
|
{
|
|
std::vector<std::string> paths;
|
|
for (auto& path : ListWalletDir()) {
|
|
paths.push_back(path.string());
|
|
}
|
|
return paths;
|
|
}
|
|
std::vector<std::unique_ptr<Wallet>> getWallets() override
|
|
{
|
|
std::vector<std::unique_ptr<Wallet>> wallets;
|
|
for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
|
|
wallets.emplace_back(MakeWallet(wallet));
|
|
}
|
|
return wallets;
|
|
}
|
|
std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) override
|
|
{
|
|
return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning));
|
|
}
|
|
WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) override
|
|
{
|
|
std::shared_ptr<CWallet> wallet;
|
|
WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warning, wallet);
|
|
result = MakeWallet(wallet);
|
|
return status;
|
|
}
|
|
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.InitMessage_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.ShowProgress_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::unique_ptr<Wallet>& wallet) { fn(std::move(wallet)); }));
|
|
}
|
|
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.BannedListChanged_connect(fn));
|
|
}
|
|
std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
|
|
{
|
|
return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](bool initial_download, const CBlockIndex* block) {
|
|
fn(initial_download, block->nHeight, block->GetBlockTime(),
|
|
GuessVerificationProgress(Params().TxData(), block));
|
|
}));
|
|
}
|
|
std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
|
|
{
|
|
return MakeHandler(
|
|
::uiInterface.NotifyHeaderTip_connect([fn](bool initial_download, const CBlockIndex* block) {
|
|
fn(initial_download, block->nHeight, block->GetBlockTime(),
|
|
GuessVerificationProgress(Params().TxData(), block));
|
|
}));
|
|
}
|
|
InitInterfaces m_interfaces;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
std::unique_ptr<Node> MakeNode() { return MakeUnique<NodeImpl>(); }
|
|
|
|
} // namespace interfaces
|