Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/bench/coin_selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ static void CoinSelection(benchmark::Bench& bench)
NodeContext node;
auto chain = interfaces::MakeChain(node);
CWallet wallet(chain.get(), /*coinjoin_loader=*/ nullptr, "", CreateDummyWalletDatabase());
wallet.SetupLegacyScriptPubKeyMan();
std::vector<std::unique_ptr<CWalletTx>> wtxs;
LOCK(wallet.cs_wallet);

Expand All @@ -55,7 +54,7 @@ static void CoinSelection(benchmark::Bench& bench)
bench.run([&] {
std::set<CInputCoin> setCoinsRet;
CAmount nValueRet;
bool success = wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, coins, setCoinsRet, nValueRet, coin_selection_params);
bool success = wallet.AttemptSelection(1003 * COIN, filter_standard, coins, setCoinsRet, nValueRet, coin_selection_params);
assert(success);
assert(nValueRet == 1003 * COIN);
assert(setCoinsRet.size() == 2);
Expand Down
16 changes: 8 additions & 8 deletions src/bench/wallet_balance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@

#include <optional>

static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const bool add_watchonly, const bool add_mine, const uint32_t epoch_iters)
static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const bool add_mine, const uint32_t epoch_iters)
{
const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
const auto& ADDRESS_WATCHONLY = ADDRESS_B58T_UNSPENDABLE;

CWallet wallet{test_setup->m_node.chain.get(), test_setup->m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase()};
{
wallet.SetupLegacyScriptPubKeyMan();
LOCK(wallet.cs_wallet);
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetupDescriptorScriptPubKeyMans();
if (wallet.LoadWallet() != DBErrors::LOAD_OK) assert(false);
}
auto handler = test_setup->m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});

const std::optional<std::string> address_mine{add_mine ? std::optional<std::string>{getnewaddress(wallet)} : std::nullopt};
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);

for (int i = 0; i < 100; ++i) {
generatetoaddress(test_setup->m_node, address_mine.value_or(ADDRESS_WATCHONLY));
Expand All @@ -40,14 +41,13 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
if (set_dirty) wallet.MarkDirty();
bal = wallet.GetBalance();
if (add_mine) assert(bal.m_mine_trusted > 0);
if (add_watchonly) assert(bal.m_watchonly_trusted > 0);
});
}

static void WalletBalanceDirty(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ true, /* add_watchonly */ true, /* add_mine */ true, 2500); }
static void WalletBalanceClean(benchmark::Bench& bench) {WalletBalance(bench, /* set_dirty */ false, /* add_watchonly */ true, /* add_mine */ true, 8000); }
static void WalletBalanceMine(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_watchonly */ false, /* add_mine */ true, 16000); }
static void WalletBalanceWatch(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_watchonly */ true, /* add_mine */ false, 8000); }
static void WalletBalanceDirty(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ true, /* add_mine */ true, 2500); }
static void WalletBalanceClean(benchmark::Bench& bench) {WalletBalance(bench, /* set_dirty */ false, /* add_mine */ true, 8000); }
static void WalletBalanceMine(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_mine */ true, 16000); }
static void WalletBalanceWatch(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_mine */ false, 8000); }

BENCHMARK(WalletBalanceDirty);
BENCHMARK(WalletBalanceClean);
Expand Down
2 changes: 1 addition & 1 deletion src/bitcoin-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ static void GetWalletBalances(UniValue& result)
}

/**
* GetProgressBar contructs a progress bar with 5% intervals.
* GetProgressBar constructs a progress bar with 5% intervals.
*
* @param[in] progress The proportion of the progress bar to be filled between 0 and 1.
* @param[out] progress_bar String representation of the progress bar.
Expand Down
4 changes: 3 additions & 1 deletion src/dummywallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
{
argsman.AddHiddenArgs({
"-avoidpartialspends",
"-consolidatefeerate=<amt>",
"-createwalletbackups=<n>",
"-disablewallet",
"-instantsendnotify=<cmd>",
Expand Down Expand Up @@ -91,7 +92,8 @@ std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet)
throw std::logic_error("Wallet function called in non-wallet build.");
}

std::unique_ptr<WalletClient> MakeWalletLoader(Chain& chain, ArgsManager& args, interfaces::CoinJoin::Loader& coinjoin_loader)
std::unique_ptr<WalletClient> MakeWalletLoader(Chain& chain, ArgsManager& args, NodeContext& node_context,
interfaces::CoinJoin::Loader& coinjoin_loader)
{
throw std::logic_error("Wallet function called in non-wallet build.");
}
Expand Down
18 changes: 18 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <index/txindex.h>
#include <interfaces/init.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <mapport.h>
#include <node/miner.h>
#include <net.h>
Expand Down Expand Up @@ -1516,6 +1517,23 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
for (const auto& client : node.chain_clients) {
client->registerRpcs();
}
#ifdef ENABLE_WALLET
// Register non-core wallet-only RPC commands. These are commands that
// aren't a part of the wallet library but heavily rely on wallet logic.
// TODO: Move them to chain client interfaces so they can be called
// with registerRpcs()
if (!args.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
for (const auto& commands : {
GetWalletCoinJoinRPCCommands(),
GetWalletEvoRPCCommands(),
GetWalletGovernanceRPCCommands(),
GetWalletMasternodeRPCCommands(),
}) {
node.wallet_loader->registerOtherRpcs(commands);
}
}
#endif // ENABLE_WALLET

#if ENABLE_ZMQ
RegisterZMQRPCCommands(tableRPC);
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/init/bitcoin-node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class BitcoinNodeInit : public interfaces::Init
}
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader) override
{
return MakeWalletLoader(chain, *Assert(m_node.args), coinjoin_loader);
return MakeWalletLoader(chain, *Assert(m_node.args), m_node, coinjoin_loader);
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
interfaces::Ipc* ipc() override { return m_ipc.get(); }
Expand Down
2 changes: 1 addition & 1 deletion src/init/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class BitcoindInit : public interfaces::Init
}
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader) override
{
return MakeWalletLoader(chain, *Assert(m_node.args), coinjoin_loader);
return MakeWalletLoader(chain, *Assert(m_node.args), m_node, coinjoin_loader);
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
NodeContext& m_node;
Expand Down
21 changes: 16 additions & 5 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,22 @@
class CCoinControl;
class CFeeRate;
class CKey;
class CRPCCommand;
class CWallet;
class UniValue;
enum class FeeReason;
enum class TransactionError;
enum isminetype : unsigned int;
struct bilingual_str;
struct CRecipient;
struct NodeContext;
struct PartiallySignedTransaction;
struct WalletContext;
struct bilingual_str;
using isminefilter = std::underlying_type<isminetype>::type;

template <typename T>
class Span;

namespace interfaces {

class Handler;
Expand Down Expand Up @@ -335,8 +339,11 @@ class Wallet
class WalletLoader : public ChainClient
{
public:
//! Create new wallet.
virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
//! Register non-core wallet RPCs
virtual void registerOtherRpcs(const Span<const CRPCCommand>& commands) = 0;

//! Create new wallet.
virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;

//! Load existing wallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
Expand All @@ -358,6 +365,9 @@ class WalletLoader : public ChainClient
//! loaded at startup or by RPC.
using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;

//! Return pointer to internal context, useful for testing.
virtual WalletContext* context() { return nullptr; }
};

//! Information about one wallet address.
Expand Down Expand Up @@ -443,11 +453,12 @@ struct WalletTxOut

//! Return implementation of Wallet interface. This function is defined in
//! dummywallet.cpp and throws if the wallet component is not compiled.
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
std::unique_ptr<Wallet> MakeWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet);

//! Return implementation of ChainClient interface for a wallet loader. This
//! function will be undefined in builds where ENABLE_WALLET is false.
std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args, CoinJoin::Loader& coinjoin_loader);
std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args, NodeContext& node_context,
CoinJoin::Loader& coinjoin_loader);

} // namespace interfaces

Expand Down
13 changes: 9 additions & 4 deletions src/qt/test/addressbooktests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,12 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
TestChain100Setup test;
node.setContext(&test.m_node);
const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", CreateMockWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
wallet->LoadWallet();
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
{
LOCK(wallet->cs_wallet);
wallet->SetupDescriptorScriptPubKeyMans();
}

auto build_address = [wallet]() {
CKey key;
Expand Down Expand Up @@ -110,9 +114,10 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
// Initialize relevant QT models.
OptionsModel optionsModel;
ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel);
RemoveWallet(wallet, std::nullopt);
WalletContext& context = *node.walletLoader().context();
AddWallet(context, wallet);
WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel);
RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());

Expand Down
24 changes: 17 additions & 7 deletions src/qt/test/wallettests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,24 @@ void TestGUI(interfaces::Node& node)
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
}
node.setContext(&test.m_node);
WalletContext& context = *node.walletLoader().context();
const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", CreateMockWalletDatabase());
AddWallet(wallet);
AddWallet(context, wallet);
wallet->LoadWallet();
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
wallet->SetAddressBook(PKHash(test.coinbaseKey.GetPubKey()), "", "receive");
spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
LOCK(wallet->cs_wallet);
wallet->SetupDescriptorScriptPubKeyMans();

// Add the coinbase key
FlatSigningProvider provider;
std::string error;
std::unique_ptr<Descriptor> desc = Parse("combo(" + EncodeSecret(test.coinbaseKey) + ")", provider, error, /* require_checksum=*/ false);
assert(desc);
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
CTxDestination dest = PKHash(test.coinbaseKey.GetPubKey());
wallet->SetAddressBook(dest, "", "receive");
wallet->SetLastBlockProcessed(105, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
}
{
Expand All @@ -134,7 +144,7 @@ void TestGUI(interfaces::Node& node)
TransactionView transactionView;
OptionsModel optionsModel;
ClientModel clientModel(node, &optionsModel);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel);
WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel);
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);

Expand Down Expand Up @@ -246,7 +256,7 @@ void TestGUI(interfaces::Node& node)
QPushButton* removeRequestButton = receiveCoinsDialog.findChild<QPushButton*>("removeRequestButton");
removeRequestButton->click();
QCOMPARE(requestTableModel->rowCount({}), currentRowCount-1);
RemoveWallet(wallet, std::nullopt);
RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt);

// Check removal from wallet
QCOMPARE(walletModel.wallet().getAddressReceiveRequests().size(), size_t{0});
Expand Down
45 changes: 35 additions & 10 deletions src/rpc/coinjoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <node/context.h>
#include <validation.h>
#include <coinjoin/context.h>
#include <coinjoin/server.h>
#include <node/context.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/server_util.h>
#include <util/check.h>
#include <rpc/util.h>
#include <util/check.h>
#include <util/strencodings.h>
#include <validation.h>
#include <wallet/rpc/util.h>
#include <walletinitinterface.h>

#ifdef ENABLE_WALLET
#include <coinjoin/client.h>
Expand Down Expand Up @@ -485,14 +486,13 @@ static RPCHelpMan getcoinjoininfo()
};
}

void RegisterCoinJoinRPCCommands(CRPCTable &t)
#ifdef ENABLE_WALLET
Span<const CRPCCommand> GetWalletCoinJoinRPCCommands()
{
// clang-format off
static const CRPCCommand commands[] =
{ // category actor (function)
// --------------------- -----------------------
{ "dash", &getcoinjoininfo, },
#ifdef ENABLE_WALLET
{ // category actor (function)
// --------------------- -----------------------
{ "dash", &coinjoin, },
{ "dash", &coinjoin_reset, },
{ "dash", &coinjoin_start, },
Expand All @@ -502,10 +502,35 @@ static const CRPCCommand commands[] =
{ "dash", &coinjoinsalt_generate, },
{ "dash", &coinjoinsalt_get, },
{ "dash", &coinjoinsalt_set, },
{ "dash", &getcoinjoininfo, },
};
// clang-format on
return commands;
}
#endif // ENABLE_WALLET

void RegisterCoinJoinRPCCommands(CRPCTable& t)
{
// clang-format off
static const CRPCCommand commands_wallet[] =
{ // category actor (function)
// --------------------- -----------------------
{ "dash", &getcoinjoininfo, },
};
// clang-format on
for (const auto& command : commands) {
t.appendCommand(command.name, &command);
// If we aren't compiling with wallet support, we still need to register RPCs that are
// capable of working without wallet support. We have to do this even if wallet support
// is compiled in but is disabled at runtime because runtime disablement prohibits
// registering wallet RPCs. We still want the reduced functionality RPC to be registered.
// TODO: Spin off these hybrid RPCs into dedicated wallet-only and/or wallet-free RPCs
// and get rid of this workaround.
if (!g_wallet_init_interface.HasWalletSupport()
#ifdef ENABLE_WALLET
|| gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)
#endif // ENABLE_WALLET
) {
for (const auto& command : commands_wallet) {
tableRPC.appendCommand(command.name, &command);
}
}
}
Loading
Loading