bitcoin/src/interface/wallet.cpp

245 lines
9.2 KiB
C++
Raw Normal View History

// 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 <interface/wallet.h>
#include <amount.h>
#include <chain.h>
#include <consensus/validation.h>
#include <interface/handler.h>
#include <net.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <script/ismine.h>
#include <script/standard.h>
#include <support/allocators/secure.h>
#include <sync.h>
#include <ui_interface.h>
#include <uint256.h>
#include <validation.h>
#include <wallet/feebumper.h>
#include <wallet/wallet.h>
#include <memory>
namespace interface {
namespace {
class PendingWalletTxImpl : public PendingWalletTx
{
public:
PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet), m_key(&wallet) {}
const CTransaction& get() override { return *m_tx; }
int64_t getVirtualSize() override { return GetVirtualTransactionSize(*m_tx); }
bool commit(WalletValueMap value_map,
WalletOrderForm order_form,
std::string from_account,
std::string& reject_reason) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
CValidationState state;
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), std::move(from_account), m_key, g_connman.get(), state)) {
reject_reason = state.GetRejectReason();
return false;
}
return true;
}
CTransactionRef m_tx;
CWallet& m_wallet;
CReserveKey m_key;
};
class WalletImpl : public Wallet
{
public:
WalletImpl(CWallet& wallet) : m_wallet(wallet) {}
bool encryptWallet(const SecureString& wallet_passphrase) override
{
return m_wallet.EncryptWallet(wallet_passphrase);
}
bool isCrypted() override { return m_wallet.IsCrypted(); }
bool lock() override { return m_wallet.Lock(); }
bool unlock(const SecureString& wallet_passphrase) override { return m_wallet.Unlock(wallet_passphrase); }
bool isLocked() override { return m_wallet.IsLocked(); }
bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
const SecureString& new_wallet_passphrase) override
{
return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase);
}
bool backupWallet(const std::string& filename) override { return m_wallet.BackupWallet(filename); }
std::string getWalletName() override { return m_wallet.GetName(); }
bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet.GetPubKey(address, pub_key); }
bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet.GetKey(address, key); }
bool isSpendable(const CTxDestination& dest) override { return IsMine(m_wallet, dest) & ISMINE_SPENDABLE; }
bool haveWatchOnly() override { return m_wallet.HaveWatchOnly(); };
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::string& purpose) override
{
return m_wallet.SetAddressBook(dest, name, purpose);
}
bool getAddress(const CTxDestination& dest, std::string* name, isminetype* is_mine) override
{
LOCK(m_wallet.cs_wallet);
auto it = m_wallet.mapAddressBook.find(dest);
if (it == m_wallet.mapAddressBook.end()) {
return false;
}
if (name) {
*name = it->second.name;
}
if (is_mine) {
*is_mine = IsMine(m_wallet, dest);
}
return true;
}
bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override
{
LOCK(m_wallet.cs_wallet);
return m_wallet.AddDestData(dest, key, value);
}
bool eraseDestData(const CTxDestination& dest, const std::string& key) override
{
LOCK(m_wallet.cs_wallet);
return m_wallet.EraseDestData(dest, key);
}
std::vector<std::string> getDestValues(const std::string& prefix) override
{
return m_wallet.GetDestValues(prefix);
}
void lockCoin(const COutPoint& output) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
return m_wallet.LockCoin(output);
}
void unlockCoin(const COutPoint& output) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
return m_wallet.UnlockCoin(output);
}
bool isLockedCoin(const COutPoint& output) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
return m_wallet.IsLockedCoin(output.hash, output.n);
}
void listLockedCoins(std::vector<COutPoint>& outputs) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
return m_wallet.ListLockedCoins(outputs);
}
std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
const CCoinControl& coin_control,
bool sign,
int& change_pos,
CAmount& fee,
std::string& fail_reason) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto pending = MakeUnique<PendingWalletTxImpl>(m_wallet);
if (!m_wallet.CreateTransaction(recipients, pending->m_tx, pending->m_key, fee, change_pos,
fail_reason, coin_control, sign)) {
return {};
}
return std::move(pending);
}
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
return m_wallet.AbandonTransaction(txid);
}
bool transactionCanBeBumped(const uint256& txid) override
{
return feebumper::TransactionCanBeBumped(&m_wallet, txid);
}
bool createBumpTransaction(const uint256& txid,
const CCoinControl& coin_control,
CAmount total_fee,
std::vector<std::string>& errors,
CAmount& old_fee,
CAmount& new_fee,
CMutableTransaction& mtx) override
{
return feebumper::CreateTransaction(&m_wallet, txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
feebumper::Result::OK;
}
bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(&m_wallet, mtx); }
bool commitBumpTransaction(const uint256& txid,
CMutableTransaction&& mtx,
std::vector<std::string>& errors,
uint256& bumped_txid) override
{
return feebumper::CommitTransaction(&m_wallet, txid, std::move(mtx), errors, bumped_txid) ==
feebumper::Result::OK;
}
WalletBalances getBalances() override
{
WalletBalances result;
result.balance = m_wallet.GetBalance();
result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance();
result.immature_balance = m_wallet.GetImmatureBalance();
result.have_watch_only = m_wallet.HaveWatchOnly();
if (result.have_watch_only) {
result.watch_only_balance = m_wallet.GetWatchOnlyBalance();
result.unconfirmed_watch_only_balance = m_wallet.GetUnconfirmedWatchOnlyBalance();
result.immature_watch_only_balance = m_wallet.GetImmatureWatchOnlyBalance();
}
return result;
}
bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
{
TRY_LOCK(cs_main, locked_chain);
if (!locked_chain) return false;
TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
}
balances = getBalances();
num_blocks = ::chainActive.Height();
return true;
}
CAmount getBalance() override { return m_wallet.GetBalance(); }
CAmount getAvailableBalance(const CCoinControl& coin_control) override
{
return m_wallet.GetAvailableBalance(&coin_control);
}
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
return MakeHandler(m_wallet.ShowProgress.connect(fn));
}
std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override
{
return MakeHandler(m_wallet.NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); }));
}
std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override
{
return MakeHandler(m_wallet.NotifyAddressBookChanged.connect(
[fn](CWallet*, const CTxDestination& address, const std::string& label, bool is_mine,
const std::string& purpose, ChangeType status) { fn(address, label, is_mine, purpose, status); }));
}
std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) override
{
return MakeHandler(m_wallet.NotifyTransactionChanged.connect(
[fn, this](CWallet*, const uint256& txid, ChangeType status) { fn(txid, status); }));
}
std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) override
{
return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
}
CWallet& m_wallet;
};
} // namespace
std::unique_ptr<Wallet> MakeWallet(CWallet& wallet) { return MakeUnique<WalletImpl>(wallet); }
} // namespace interface