mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 14:53:43 +01:00
wallet: Remove isminetype
Since the only remaining isminetypes are ISMINE_NO and ISMINE_SPENDABLE, this enum is now just a bool and can be removed. IsMine is changed to return a bool and any usage of isminetypes and isminefilters are changed to be the remaining ISMINE_SPENDABLE case.
This commit is contained in:
@@ -14,7 +14,6 @@
|
|||||||
#include <wallet/context.h>
|
#include <wallet/context.h>
|
||||||
#include <wallet/db.h>
|
#include <wallet/db.h>
|
||||||
#include <wallet/test/util.h>
|
#include <wallet/test/util.h>
|
||||||
#include <wallet/types.h>
|
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
#include <wallet/walletutil.h>
|
#include <wallet/walletutil.h>
|
||||||
|
|
||||||
@@ -58,8 +57,8 @@ static void WalletIsMine(benchmark::Bench& bench, int num_combo = 0)
|
|||||||
|
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK(wallet->cs_wallet);
|
||||||
isminetype mine = wallet->IsMine(script);
|
bool mine = wallet->IsMine(script);
|
||||||
assert(mine == ISMINE_NO);
|
assert(!mine);
|
||||||
});
|
});
|
||||||
|
|
||||||
TestUnloadWallet(std::move(wallet));
|
TestUnloadWallet(std::move(wallet));
|
||||||
|
|||||||
@@ -43,10 +43,8 @@ namespace wallet {
|
|||||||
class CCoinControl;
|
class CCoinControl;
|
||||||
class CWallet;
|
class CWallet;
|
||||||
enum class AddressPurpose;
|
enum class AddressPurpose;
|
||||||
enum isminetype : unsigned int;
|
|
||||||
struct CRecipient;
|
struct CRecipient;
|
||||||
struct WalletContext;
|
struct WalletContext;
|
||||||
using isminefilter = std::underlying_type_t<isminetype>;
|
|
||||||
} // namespace wallet
|
} // namespace wallet
|
||||||
|
|
||||||
namespace interfaces {
|
namespace interfaces {
|
||||||
@@ -224,16 +222,16 @@ public:
|
|||||||
virtual CAmount getAvailableBalance(const wallet::CCoinControl& coin_control) = 0;
|
virtual CAmount getAvailableBalance(const wallet::CCoinControl& coin_control) = 0;
|
||||||
|
|
||||||
//! Return whether transaction input belongs to wallet.
|
//! Return whether transaction input belongs to wallet.
|
||||||
virtual wallet::isminetype txinIsMine(const CTxIn& txin) = 0;
|
virtual bool txinIsMine(const CTxIn& txin) = 0;
|
||||||
|
|
||||||
//! Return whether transaction output belongs to wallet.
|
//! Return whether transaction output belongs to wallet.
|
||||||
virtual wallet::isminetype txoutIsMine(const CTxOut& txout) = 0;
|
virtual bool txoutIsMine(const CTxOut& txout) = 0;
|
||||||
|
|
||||||
//! Return debit amount if transaction input belongs to wallet.
|
//! Return debit amount if transaction input belongs to wallet.
|
||||||
virtual CAmount getDebit(const CTxIn& txin, wallet::isminefilter filter) = 0;
|
virtual CAmount getDebit(const CTxIn& txin) = 0;
|
||||||
|
|
||||||
//! Return credit amount if transaction input belongs to wallet.
|
//! Return credit amount if transaction input belongs to wallet.
|
||||||
virtual CAmount getCredit(const CTxOut& txout, wallet::isminefilter filter) = 0;
|
virtual CAmount getCredit(const CTxOut& txout) = 0;
|
||||||
|
|
||||||
//! Return AvailableCoins + LockedCoins grouped by wallet address.
|
//! Return AvailableCoins + LockedCoins grouped by wallet address.
|
||||||
//! (put change in one group with wallet address)
|
//! (put change in one group with wallet address)
|
||||||
@@ -355,11 +353,11 @@ public:
|
|||||||
struct WalletAddress
|
struct WalletAddress
|
||||||
{
|
{
|
||||||
CTxDestination dest;
|
CTxDestination dest;
|
||||||
wallet::isminetype is_mine;
|
bool is_mine;
|
||||||
wallet::AddressPurpose purpose;
|
wallet::AddressPurpose purpose;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
WalletAddress(CTxDestination dest, wallet::isminetype is_mine, wallet::AddressPurpose purpose, std::string name)
|
WalletAddress(CTxDestination dest, bool is_mine, wallet::AddressPurpose purpose, std::string name)
|
||||||
: dest(std::move(dest)), is_mine(is_mine), purpose(std::move(purpose)), name(std::move(name))
|
: dest(std::move(dest)), is_mine(is_mine), purpose(std::move(purpose)), name(std::move(name))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -383,11 +381,11 @@ struct WalletBalances
|
|||||||
struct WalletTx
|
struct WalletTx
|
||||||
{
|
{
|
||||||
CTransactionRef tx;
|
CTransactionRef tx;
|
||||||
std::vector<wallet::isminetype> txin_is_mine;
|
std::vector<bool> txin_is_mine;
|
||||||
std::vector<wallet::isminetype> txout_is_mine;
|
std::vector<bool> txout_is_mine;
|
||||||
std::vector<bool> txout_is_change;
|
std::vector<bool> txout_is_change;
|
||||||
std::vector<CTxDestination> txout_address;
|
std::vector<CTxDestination> txout_address;
|
||||||
std::vector<wallet::isminetype> txout_address_is_mine;
|
std::vector<bool> txout_address_is_mine;
|
||||||
CAmount credit;
|
CAmount credit;
|
||||||
CAmount debit;
|
CAmount debit;
|
||||||
CAmount change;
|
CAmount change;
|
||||||
|
|||||||
@@ -17,17 +17,12 @@
|
|||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <wallet/types.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <QLatin1String>
|
#include <QLatin1String>
|
||||||
|
|
||||||
using wallet::ISMINE_ALL;
|
|
||||||
using wallet::ISMINE_SPENDABLE;
|
|
||||||
using wallet::isminetype;
|
|
||||||
|
|
||||||
QString TransactionDesc::FormatTxStatus(const interfaces::WalletTxStatus& status, bool inMempool)
|
QString TransactionDesc::FormatTxStatus(const interfaces::WalletTxStatus& status, bool inMempool)
|
||||||
{
|
{
|
||||||
int depth = status.depth_in_main_chain;
|
int depth = status.depth_in_main_chain;
|
||||||
@@ -185,7 +180,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
//
|
//
|
||||||
CAmount nUnmatured = 0;
|
CAmount nUnmatured = 0;
|
||||||
for (const CTxOut& txout : wtx.tx->vout)
|
for (const CTxOut& txout : wtx.tx->vout)
|
||||||
nUnmatured += wallet.getCredit(txout, ISMINE_ALL);
|
nUnmatured += wallet.getCredit(txout);
|
||||||
strHTML += "<b>" + tr("Credit") + ":</b> ";
|
strHTML += "<b>" + tr("Credit") + ":</b> ";
|
||||||
if (status.is_in_main_chain)
|
if (status.is_in_main_chain)
|
||||||
strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", status.blocks_to_maturity) + ")";
|
strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", status.blocks_to_maturity) + ")";
|
||||||
@@ -202,19 +197,10 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isminetype fAllFromMe = ISMINE_SPENDABLE;
|
bool all_from_me = std::all_of(wtx.txin_is_mine.begin(), wtx.txin_is_mine.end(), [](bool mine) { return mine; });
|
||||||
for (const isminetype mine : wtx.txin_is_mine)
|
bool all_to_me = std::all_of(wtx.txout_is_mine.begin(), wtx.txout_is_mine.end(), [](bool mine) { return mine; });
|
||||||
{
|
|
||||||
if(fAllFromMe > mine) fAllFromMe = mine;
|
|
||||||
}
|
|
||||||
|
|
||||||
isminetype fAllToMe = ISMINE_SPENDABLE;
|
if (all_from_me)
|
||||||
for (const isminetype mine : wtx.txout_is_mine)
|
|
||||||
{
|
|
||||||
if(fAllToMe > mine) fAllToMe = mine;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fAllFromMe)
|
|
||||||
{
|
{
|
||||||
// Debit
|
// Debit
|
||||||
//
|
//
|
||||||
@@ -222,8 +208,8 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
for (const CTxOut& txout : wtx.tx->vout)
|
for (const CTxOut& txout : wtx.tx->vout)
|
||||||
{
|
{
|
||||||
// Ignore change
|
// Ignore change
|
||||||
isminetype toSelf = *(mine++);
|
bool toSelf = *(mine++);
|
||||||
if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
|
if (toSelf && all_from_me)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!wtx.value_map.count("to") || wtx.value_map["to"].empty())
|
if (!wtx.value_map.count("to") || wtx.value_map["to"].empty())
|
||||||
@@ -238,7 +224,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
address, &name, /*purpose=*/nullptr) && !name.empty())
|
address, &name, /*purpose=*/nullptr) && !name.empty())
|
||||||
strHTML += GUIUtil::HtmlEscape(name) + " ";
|
strHTML += GUIUtil::HtmlEscape(name) + " ";
|
||||||
strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));
|
strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));
|
||||||
if(toSelf == ISMINE_SPENDABLE)
|
if(toSelf)
|
||||||
strHTML += " (" + tr("own address") + ")";
|
strHTML += " (" + tr("own address") + ")";
|
||||||
strHTML += "<br>";
|
strHTML += "<br>";
|
||||||
}
|
}
|
||||||
@@ -249,7 +235,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
|
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fAllToMe)
|
if (all_to_me)
|
||||||
{
|
{
|
||||||
// Payment to self
|
// Payment to self
|
||||||
CAmount nChange = wtx.change;
|
CAmount nChange = wtx.change;
|
||||||
@@ -270,13 +256,13 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
auto mine = wtx.txin_is_mine.begin();
|
auto mine = wtx.txin_is_mine.begin();
|
||||||
for (const CTxIn& txin : wtx.tx->vin) {
|
for (const CTxIn& txin : wtx.tx->vin) {
|
||||||
if (*(mine++)) {
|
if (*(mine++)) {
|
||||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet.getDebit(txin, ISMINE_ALL)) + "<br>";
|
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet.getDebit(txin)) + "<br>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mine = wtx.txout_is_mine.begin();
|
mine = wtx.txout_is_mine.begin();
|
||||||
for (const CTxOut& txout : wtx.tx->vout) {
|
for (const CTxOut& txout : wtx.tx->vout) {
|
||||||
if (*(mine++)) {
|
if (*(mine++)) {
|
||||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet.getCredit(txout, ISMINE_ALL)) + "<br>";
|
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet.getCredit(txout)) + "<br>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,10 +319,10 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
|
strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
|
||||||
for (const CTxIn& txin : wtx.tx->vin)
|
for (const CTxIn& txin : wtx.tx->vin)
|
||||||
if(wallet.txinIsMine(txin))
|
if(wallet.txinIsMine(txin))
|
||||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet.getDebit(txin, ISMINE_ALL)) + "<br>";
|
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet.getDebit(txin)) + "<br>";
|
||||||
for (const CTxOut& txout : wtx.tx->vout)
|
for (const CTxOut& txout : wtx.tx->vout)
|
||||||
if(wallet.txoutIsMine(txout))
|
if(wallet.txoutIsMine(txout))
|
||||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet.getCredit(txout, ISMINE_ALL)) + "<br>";
|
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet.getCredit(txout)) + "<br>";
|
||||||
|
|
||||||
strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
|
strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
|
||||||
strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);
|
strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);
|
||||||
@@ -361,7 +347,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||||||
strHTML += QString::fromStdString(EncodeDestination(address));
|
strHTML += QString::fromStdString(EncodeDestination(address));
|
||||||
}
|
}
|
||||||
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
|
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
|
||||||
strHTML = strHTML + " IsMine=" + (wallet.txoutIsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
|
strHTML = strHTML + " IsMine=" + (wallet.txoutIsMine(vout) ? tr("true") : tr("false")) + "</li>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,11 @@
|
|||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <interfaces/wallet.h>
|
#include <interfaces/wallet.h>
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <wallet/types.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
using wallet::ISMINE_NO;
|
|
||||||
using wallet::ISMINE_SPENDABLE;
|
|
||||||
using wallet::isminetype;
|
|
||||||
|
|
||||||
/* Return positive answer if transaction should be shown in list.
|
/* Return positive answer if transaction should be shown in list.
|
||||||
*/
|
*/
|
||||||
bool TransactionRecord::showTransaction()
|
bool TransactionRecord::showTransaction()
|
||||||
@@ -39,26 +34,26 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
|
|||||||
Txid hash = wtx.tx->GetHash();
|
Txid hash = wtx.tx->GetHash();
|
||||||
std::map<std::string, std::string> mapValue = wtx.value_map;
|
std::map<std::string, std::string> mapValue = wtx.value_map;
|
||||||
|
|
||||||
isminetype fAllFromMe = ISMINE_SPENDABLE;
|
bool all_from_me = true;
|
||||||
bool any_from_me = false;
|
bool any_from_me = false;
|
||||||
if (wtx.is_coinbase) {
|
if (wtx.is_coinbase) {
|
||||||
fAllFromMe = ISMINE_NO;
|
all_from_me = false;
|
||||||
} else {
|
} else {
|
||||||
for (const isminetype mine : wtx.txin_is_mine)
|
for (const bool mine : wtx.txin_is_mine)
|
||||||
{
|
{
|
||||||
if(fAllFromMe > mine) fAllFromMe = mine;
|
all_from_me = all_from_me && mine;
|
||||||
if (mine) any_from_me = true;
|
if (mine) any_from_me = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fAllFromMe || !any_from_me) {
|
if (all_from_me || !any_from_me) {
|
||||||
CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
|
CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
|
||||||
|
|
||||||
for(unsigned int i = 0; i < wtx.tx->vout.size(); i++)
|
for(unsigned int i = 0; i < wtx.tx->vout.size(); i++)
|
||||||
{
|
{
|
||||||
const CTxOut& txout = wtx.tx->vout[i];
|
const CTxOut& txout = wtx.tx->vout[i];
|
||||||
|
|
||||||
if (fAllFromMe) {
|
if (all_from_me) {
|
||||||
// Change is only really possible if we're the sender
|
// Change is only really possible if we're the sender
|
||||||
// Otherwise, someone just sent bitcoins to a change address, which should be shown
|
// Otherwise, someone just sent bitcoins to a change address, which should be shown
|
||||||
if (wtx.txout_is_change[i]) {
|
if (wtx.txout_is_change[i]) {
|
||||||
@@ -97,7 +92,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
|
|||||||
parts.append(sub);
|
parts.append(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype mine = wtx.txout_is_mine[i];
|
bool mine = wtx.txout_is_mine[i];
|
||||||
if(mine)
|
if(mine)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <common/system.h>
|
#include <common/system.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <node/types.h>
|
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <util/moneystr.h>
|
#include <util/moneystr.h>
|
||||||
@@ -48,8 +47,7 @@ static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWallet
|
|||||||
if (require_mine) {
|
if (require_mine) {
|
||||||
// check that original tx consists entirely of our inputs
|
// check that original tx consists entirely of our inputs
|
||||||
// if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
|
// if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
if (!AllInputsMine(wallet, *wtx.tx)) {
|
||||||
if (!AllInputsMine(wallet, *wtx.tx, filter)) {
|
|
||||||
errors.emplace_back(Untranslated("Transaction contains inputs that don't belong to this wallet"));
|
errors.emplace_back(Untranslated("Transaction contains inputs that don't belong to this wallet"));
|
||||||
return feebumper::Result::WALLET_ERROR;
|
return feebumper::Result::WALLET_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <wallet/context.h>
|
#include <wallet/context.h>
|
||||||
#include <wallet/feebumper.h>
|
#include <wallet/feebumper.h>
|
||||||
#include <wallet/fees.h>
|
#include <wallet/fees.h>
|
||||||
#include <wallet/types.h>
|
|
||||||
#include <wallet/load.h>
|
#include <wallet/load.h>
|
||||||
#include <wallet/receive.h>
|
#include <wallet/receive.h>
|
||||||
#include <wallet/rpc/wallet.h>
|
#include <wallet/rpc/wallet.h>
|
||||||
@@ -74,10 +73,10 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
|
|||||||
result.txout_address.emplace_back();
|
result.txout_address.emplace_back();
|
||||||
result.txout_address_is_mine.emplace_back(ExtractDestination(txout.scriptPubKey, result.txout_address.back()) ?
|
result.txout_address_is_mine.emplace_back(ExtractDestination(txout.scriptPubKey, result.txout_address.back()) ?
|
||||||
wallet.IsMine(result.txout_address.back()) :
|
wallet.IsMine(result.txout_address.back()) :
|
||||||
ISMINE_NO);
|
false);
|
||||||
}
|
}
|
||||||
result.credit = CachedTxGetCredit(wallet, wtx, ISMINE_ALL, /*avoid_reuse=*/true);
|
result.credit = CachedTxGetCredit(wallet, wtx, /*avoid_reuse=*/true);
|
||||||
result.debit = CachedTxGetDebit(wallet, wtx, ISMINE_ALL, /*avoid_reuse=*/true);
|
result.debit = CachedTxGetDebit(wallet, wtx, /*avoid_reuse=*/true);
|
||||||
result.change = CachedTxGetChange(wallet, wtx);
|
result.change = CachedTxGetChange(wallet, wtx);
|
||||||
result.time = wtx.GetTxTime();
|
result.time = wtx.GetTxTime();
|
||||||
result.value_map = wtx.mapValue;
|
result.value_map = wtx.mapValue;
|
||||||
@@ -173,7 +172,7 @@ public:
|
|||||||
bool isSpendable(const CTxDestination& dest) override
|
bool isSpendable(const CTxDestination& dest) override
|
||||||
{
|
{
|
||||||
LOCK(m_wallet->cs_wallet);
|
LOCK(m_wallet->cs_wallet);
|
||||||
return m_wallet->IsMine(dest) & ISMINE_SPENDABLE;
|
return m_wallet->IsMine(dest);
|
||||||
}
|
}
|
||||||
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<AddressPurpose>& purpose) override
|
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<AddressPurpose>& purpose) override
|
||||||
{
|
{
|
||||||
@@ -205,7 +204,7 @@ public:
|
|||||||
std::vector<WalletAddress> result;
|
std::vector<WalletAddress> result;
|
||||||
m_wallet->ForEachAddrBookEntry([&](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet) {
|
m_wallet->ForEachAddrBookEntry([&](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet) {
|
||||||
if (is_change) return;
|
if (is_change) return;
|
||||||
isminetype is_mine = m_wallet->IsMine(dest);
|
bool is_mine = m_wallet->IsMine(dest);
|
||||||
// In very old wallets, address purpose may not be recorded so we derive it from IsMine
|
// In very old wallets, address purpose may not be recorded so we derive it from IsMine
|
||||||
result.emplace_back(dest, is_mine, purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND), label);
|
result.emplace_back(dest, is_mine, purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND), label);
|
||||||
});
|
});
|
||||||
@@ -423,25 +422,25 @@ public:
|
|||||||
|
|
||||||
return total_amount;
|
return total_amount;
|
||||||
}
|
}
|
||||||
isminetype txinIsMine(const CTxIn& txin) override
|
bool txinIsMine(const CTxIn& txin) override
|
||||||
{
|
{
|
||||||
LOCK(m_wallet->cs_wallet);
|
LOCK(m_wallet->cs_wallet);
|
||||||
return InputIsMine(*m_wallet, txin);
|
return InputIsMine(*m_wallet, txin);
|
||||||
}
|
}
|
||||||
isminetype txoutIsMine(const CTxOut& txout) override
|
bool txoutIsMine(const CTxOut& txout) override
|
||||||
{
|
{
|
||||||
LOCK(m_wallet->cs_wallet);
|
LOCK(m_wallet->cs_wallet);
|
||||||
return m_wallet->IsMine(txout);
|
return m_wallet->IsMine(txout);
|
||||||
}
|
}
|
||||||
CAmount getDebit(const CTxIn& txin, isminefilter filter) override
|
CAmount getDebit(const CTxIn& txin) override
|
||||||
{
|
{
|
||||||
LOCK(m_wallet->cs_wallet);
|
LOCK(m_wallet->cs_wallet);
|
||||||
return m_wallet->GetDebit(txin, filter);
|
return m_wallet->GetDebit(txin);
|
||||||
}
|
}
|
||||||
CAmount getCredit(const CTxOut& txout, isminefilter filter) override
|
CAmount getCredit(const CTxOut& txout) override
|
||||||
{
|
{
|
||||||
LOCK(m_wallet->cs_wallet);
|
LOCK(m_wallet->cs_wallet);
|
||||||
return OutputGetCredit(*m_wallet, txout, filter);
|
return OutputGetCredit(*m_wallet, txout);
|
||||||
}
|
}
|
||||||
CoinsList listCoins() override
|
CoinsList listCoins() override
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,39 +10,39 @@
|
|||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
namespace wallet {
|
namespace wallet {
|
||||||
isminetype InputIsMine(const CWallet& wallet, const CTxIn& txin)
|
bool InputIsMine(const CWallet& wallet, const CTxIn& txin)
|
||||||
{
|
{
|
||||||
AssertLockHeld(wallet.cs_wallet);
|
AssertLockHeld(wallet.cs_wallet);
|
||||||
const CWalletTx* prev = wallet.GetWalletTx(txin.prevout.hash);
|
const CWalletTx* prev = wallet.GetWalletTx(txin.prevout.hash);
|
||||||
if (prev && txin.prevout.n < prev->tx->vout.size()) {
|
if (prev && txin.prevout.n < prev->tx->vout.size()) {
|
||||||
return wallet.IsMine(prev->tx->vout[txin.prevout.n]);
|
return wallet.IsMine(prev->tx->vout[txin.prevout.n]);
|
||||||
}
|
}
|
||||||
return ISMINE_NO;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
|
bool AllInputsMine(const CWallet& wallet, const CTransaction& tx)
|
||||||
{
|
{
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
for (const CTxIn& txin : tx.vin) {
|
for (const CTxIn& txin : tx.vin) {
|
||||||
if (!(InputIsMine(wallet, txin) & filter)) return false;
|
if (!InputIsMine(wallet, txin)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout, const isminefilter& filter)
|
CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout)
|
||||||
{
|
{
|
||||||
if (!MoneyRange(txout.nValue))
|
if (!MoneyRange(txout.nValue))
|
||||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
return ((wallet.IsMine(txout) & filter) ? txout.nValue : 0);
|
return (wallet.IsMine(txout) ? txout.nValue : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
|
CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx)
|
||||||
{
|
{
|
||||||
CAmount nCredit = 0;
|
CAmount nCredit = 0;
|
||||||
for (const CTxOut& txout : tx.vout)
|
for (const CTxOut& txout : tx.vout)
|
||||||
{
|
{
|
||||||
nCredit += OutputGetCredit(wallet, txout, filter);
|
nCredit += OutputGetCredit(wallet, txout);
|
||||||
if (!MoneyRange(nCredit))
|
if (!MoneyRange(nCredit))
|
||||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||||
}
|
}
|
||||||
@@ -97,17 +97,17 @@ CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx)
|
|||||||
return nChange;
|
return nChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter, bool avoid_reuse)
|
static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, bool avoid_reuse)
|
||||||
{
|
{
|
||||||
auto& amount = wtx.m_amounts[type];
|
auto& amount = wtx.m_amounts[type];
|
||||||
if (!amount.IsCached(avoid_reuse)) {
|
if (!amount.IsCached(avoid_reuse)) {
|
||||||
amount.Set(avoid_reuse, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx, filter) : TxGetCredit(wallet, *wtx.tx, filter));
|
amount.Set(avoid_reuse, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx) : TxGetCredit(wallet, *wtx.tx));
|
||||||
wtx.m_is_cache_empty = false;
|
wtx.m_is_cache_empty = false;
|
||||||
}
|
}
|
||||||
return amount.Get(avoid_reuse);
|
return amount.Get(avoid_reuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter, bool avoid_reuse)
|
CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, bool avoid_reuse)
|
||||||
{
|
{
|
||||||
AssertLockHeld(wallet.cs_wallet);
|
AssertLockHeld(wallet.cs_wallet);
|
||||||
|
|
||||||
@@ -115,26 +115,16 @@ CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const ism
|
|||||||
if (wallet.IsTxImmatureCoinBase(wtx))
|
if (wallet.IsTxImmatureCoinBase(wtx))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CAmount credit = 0;
|
// GetBalance can assume transactions in mapWallet won't change
|
||||||
const isminefilter get_amount_filter{filter & ISMINE_ALL};
|
return GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, avoid_reuse);
|
||||||
if (get_amount_filter) {
|
|
||||||
// GetBalance can assume transactions in mapWallet won't change
|
|
||||||
credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, get_amount_filter, avoid_reuse);
|
|
||||||
}
|
|
||||||
return credit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter, bool avoid_reuse)
|
CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, bool avoid_reuse)
|
||||||
{
|
{
|
||||||
if (wtx.tx->vin.empty())
|
if (wtx.tx->vin.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CAmount debit = 0;
|
return GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, avoid_reuse);
|
||||||
const isminefilter get_amount_filter{filter & ISMINE_ALL};
|
|
||||||
if (get_amount_filter) {
|
|
||||||
debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, get_amount_filter, avoid_reuse);
|
|
||||||
}
|
|
||||||
return debit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
|
CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
|
||||||
@@ -148,7 +138,7 @@ CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
|
|||||||
|
|
||||||
void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
||||||
std::list<COutputEntry>& listReceived,
|
std::list<COutputEntry>& listReceived,
|
||||||
std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter,
|
std::list<COutputEntry>& listSent, CAmount& nFee,
|
||||||
bool include_change)
|
bool include_change)
|
||||||
{
|
{
|
||||||
nFee = 0;
|
nFee = 0;
|
||||||
@@ -156,7 +146,7 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
|||||||
listSent.clear();
|
listSent.clear();
|
||||||
|
|
||||||
// Compute fee:
|
// Compute fee:
|
||||||
CAmount nDebit = CachedTxGetDebit(wallet, wtx, filter, /*avoid_reuse=*/false);
|
CAmount nDebit = CachedTxGetDebit(wallet, wtx, /*avoid_reuse=*/false);
|
||||||
if (nDebit > 0) // debit>0 means we signed/sent this transaction
|
if (nDebit > 0) // debit>0 means we signed/sent this transaction
|
||||||
{
|
{
|
||||||
CAmount nValueOut = wtx.tx->GetValueOut();
|
CAmount nValueOut = wtx.tx->GetValueOut();
|
||||||
@@ -168,7 +158,7 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
|||||||
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
|
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
|
||||||
{
|
{
|
||||||
const CTxOut& txout = wtx.tx->vout[i];
|
const CTxOut& txout = wtx.tx->vout[i];
|
||||||
isminetype fIsMine = wallet.IsMine(txout);
|
bool ismine = wallet.IsMine(txout);
|
||||||
// Only need to handle txouts if AT LEAST one of these is true:
|
// Only need to handle txouts if AT LEAST one of these is true:
|
||||||
// 1) they debit from us (sent)
|
// 1) they debit from us (sent)
|
||||||
// 2) the output is to us (received)
|
// 2) the output is to us (received)
|
||||||
@@ -177,7 +167,7 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
|||||||
if (!include_change && OutputIsChange(wallet, txout))
|
if (!include_change && OutputIsChange(wallet, txout))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!(fIsMine & filter))
|
else if (!ismine)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// In either case, we need to get the destination address
|
// In either case, we need to get the destination address
|
||||||
@@ -197,15 +187,15 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
|||||||
listSent.push_back(output);
|
listSent.push_back(output);
|
||||||
|
|
||||||
// If we are receiving the output, add it as a "received" entry
|
// If we are receiving the output, add it as a "received" entry
|
||||||
if (fIsMine & filter)
|
if (ismine)
|
||||||
listReceived.push_back(output);
|
listReceived.push_back(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
|
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx)
|
||||||
{
|
{
|
||||||
return (CachedTxGetDebit(wallet, wtx, filter, /*avoid_reuse=*/false) > 0);
|
return (CachedTxGetDebit(wallet, wtx, /*avoid_reuse=*/false) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTNEXTLINE(misc-no-recursion)
|
// NOLINTNEXTLINE(misc-no-recursion)
|
||||||
@@ -219,7 +209,7 @@ bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<Txi
|
|||||||
if (wtx.isConfirmed()) return true;
|
if (wtx.isConfirmed()) return true;
|
||||||
if (wtx.isBlockConflicted()) return false;
|
if (wtx.isBlockConflicted()) return false;
|
||||||
// using wtx's cached debit
|
// using wtx's cached debit
|
||||||
if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
|
if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx)) return false;
|
||||||
|
|
||||||
// Don't trust unconfirmed transactions from us unless they are in the mempool.
|
// Don't trust unconfirmed transactions from us unless they are in the mempool.
|
||||||
if (!wtx.InMempool()) return false;
|
if (!wtx.InMempool()) return false;
|
||||||
@@ -232,7 +222,7 @@ bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<Txi
|
|||||||
if (parent == nullptr) return false;
|
if (parent == nullptr) return false;
|
||||||
const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
|
const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
|
||||||
// Check that this specific input being spent is trusted
|
// Check that this specific input being spent is trusted
|
||||||
if (wallet.IsMine(parentOut) != ISMINE_SPENDABLE) return false;
|
if (!wallet.IsMine(parentOut)) return false;
|
||||||
// If we've already trusted this parent, continue
|
// If we've already trusted this parent, continue
|
||||||
if (trusted_parents.count(parent->GetHash())) continue;
|
if (trusted_parents.count(parent->GetHash())) continue;
|
||||||
// Recurse to check that the parent is also trusted
|
// Recurse to check that the parent is also trusted
|
||||||
@@ -264,13 +254,7 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
|
|||||||
|
|
||||||
if (!wallet.IsSpent(outpoint) && (allow_used_addresses || !wallet.IsSpentKey(txo.GetTxOut().scriptPubKey))) {
|
if (!wallet.IsSpent(outpoint) && (allow_used_addresses || !wallet.IsSpentKey(txo.GetTxOut().scriptPubKey))) {
|
||||||
// Get the amounts for mine
|
// Get the amounts for mine
|
||||||
CAmount credit_mine = 0;
|
CAmount credit_mine = txo.GetTxOut().nValue;
|
||||||
if (txo.GetIsMine() == ISMINE_SPENDABLE) {
|
|
||||||
credit_mine = txo.GetTxOut().nValue;
|
|
||||||
} else {
|
|
||||||
// We shouldn't see any other isminetypes
|
|
||||||
Assume(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the amounts in the return object
|
// Set the amounts in the return object
|
||||||
if (wallet.IsTxImmatureCoinBase(wtx) && wtx.isConfirmed()) {
|
if (wallet.IsTxImmatureCoinBase(wtx) && wtx.isConfirmed()) {
|
||||||
@@ -300,7 +284,7 @@ std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
|
|||||||
if (wallet.IsTxImmatureCoinBase(wtx)) continue;
|
if (wallet.IsTxImmatureCoinBase(wtx)) continue;
|
||||||
|
|
||||||
int nDepth = wallet.GetTxDepthInMainChain(wtx);
|
int nDepth = wallet.GetTxDepthInMainChain(wtx);
|
||||||
if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1)) continue;
|
if (nDepth < (CachedTxIsFromMe(wallet, wtx) ? 0 : 1)) continue;
|
||||||
|
|
||||||
CTxDestination addr;
|
CTxDestination addr;
|
||||||
Assume(wallet.IsMine(txo.GetTxOut()));
|
Assume(wallet.IsMine(txo.GetTxOut()));
|
||||||
|
|||||||
@@ -8,27 +8,25 @@
|
|||||||
#include <consensus/amount.h>
|
#include <consensus/amount.h>
|
||||||
#include <primitives/transaction_identifier.h>
|
#include <primitives/transaction_identifier.h>
|
||||||
#include <wallet/transaction.h>
|
#include <wallet/transaction.h>
|
||||||
#include <wallet/types.h>
|
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
namespace wallet {
|
namespace wallet {
|
||||||
isminetype InputIsMine(const CWallet& wallet, const CTxIn& txin) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
bool InputIsMine(const CWallet& wallet, const CTxIn& txin) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
|
|
||||||
/** Returns whether all of the inputs match the filter */
|
/** Returns whether all of the inputs belong to the wallet*/
|
||||||
bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter);
|
bool AllInputsMine(const CWallet& wallet, const CTransaction& tx);
|
||||||
|
|
||||||
CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout, const isminefilter& filter);
|
CAmount OutputGetCredit(const CWallet& wallet, const CTxOut& txout);
|
||||||
CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter);
|
CAmount TxGetCredit(const CWallet& wallet, const CTransaction& tx);
|
||||||
|
|
||||||
bool ScriptIsChange(const CWallet& wallet, const CScript& script) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
bool ScriptIsChange(const CWallet& wallet, const CScript& script) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
bool OutputIsChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
bool OutputIsChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx);
|
CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx);
|
||||||
|
|
||||||
CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter, bool avoid_reuse)
|
CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, bool avoid_reuse)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
//! filter decides which addresses will count towards the debit
|
CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, bool avoid_reuse);
|
||||||
CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter, bool avoid_reuse);
|
|
||||||
CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx);
|
CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx);
|
||||||
struct COutputEntry
|
struct COutputEntry
|
||||||
{
|
{
|
||||||
@@ -39,9 +37,9 @@ struct COutputEntry
|
|||||||
void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
||||||
std::list<COutputEntry>& listReceived,
|
std::list<COutputEntry>& listReceived,
|
||||||
std::list<COutputEntry>& listSent,
|
std::list<COutputEntry>& listSent,
|
||||||
CAmount& nFee, const isminefilter& filter,
|
CAmount& nFee,
|
||||||
bool include_change);
|
bool include_change);
|
||||||
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter);
|
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx);
|
||||||
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<Txid>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<Txid>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
||||||
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx);
|
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx);
|
||||||
|
|
||||||
|
|||||||
@@ -448,8 +448,8 @@ RPCHelpMan getaddressinfo()
|
|||||||
|
|
||||||
std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
|
std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
|
||||||
|
|
||||||
isminetype mine = pwallet->IsMine(dest);
|
bool mine = pwallet->IsMine(dest);
|
||||||
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
|
ret.pushKV("ismine", mine);
|
||||||
|
|
||||||
if (provider) {
|
if (provider) {
|
||||||
auto inferred = InferDescriptor(scriptPubKey, *provider);
|
auto inferred = InferDescriptor(scriptPubKey, *provider);
|
||||||
|
|||||||
@@ -1505,7 +1505,7 @@ RPCHelpMan sendall()
|
|||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));
|
||||||
}
|
}
|
||||||
const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};
|
const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};
|
||||||
if (!tx || input.prevout.n >= tx->tx->vout.size() || !(pwallet->IsMine(tx->tx->vout[input.prevout.n]) & ISMINE_SPENDABLE)) {
|
if (!tx || input.prevout.n >= tx->tx->vout.size() || !pwallet->IsMine(tx->tx->vout[input.prevout.n])) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));
|
||||||
}
|
}
|
||||||
if (pwallet->GetTxDepthInMainChain(*tx) == 0) {
|
if (pwallet->GetTxDepthInMainChain(*tx) == 0) {
|
||||||
|
|||||||
@@ -83,8 +83,6 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
|
|||||||
if (!params[1].isNull())
|
if (!params[1].isNull())
|
||||||
fIncludeEmpty = params[1].get_bool();
|
fIncludeEmpty = params[1].get_bool();
|
||||||
|
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
|
||||||
|
|
||||||
std::optional<CTxDestination> filtered_address{std::nullopt};
|
std::optional<CTxDestination> filtered_address{std::nullopt};
|
||||||
if (!by_label && !params[3].isNull() && !params[3].get_str().empty()) {
|
if (!by_label && !params[3].isNull() && !params[3].get_str().empty()) {
|
||||||
if (!IsValidDestinationString(params[3].get_str())) {
|
if (!IsValidDestinationString(params[3].get_str())) {
|
||||||
@@ -116,8 +114,7 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
isminefilter mine = wallet.IsMine(address);
|
if (!wallet.IsMine(address))
|
||||||
if (!(mine & filter))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tallyitem& item = mapTally[address];
|
tallyitem& item = mapTally[address];
|
||||||
@@ -302,12 +299,11 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
|
|||||||
* @param nMinDepth The minimum confirmation depth.
|
* @param nMinDepth The minimum confirmation depth.
|
||||||
* @param fLong Whether to include the JSON version of the transaction.
|
* @param fLong Whether to include the JSON version of the transaction.
|
||||||
* @param ret The vector into which the result is stored.
|
* @param ret The vector into which the result is stored.
|
||||||
* @param filter_ismine The "is mine" filter flags.
|
|
||||||
* @param filter_label Optional label string to filter incoming transactions.
|
* @param filter_label Optional label string to filter incoming transactions.
|
||||||
*/
|
*/
|
||||||
template <class Vec>
|
template <class Vec>
|
||||||
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
|
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
|
||||||
Vec& ret, const isminefilter& filter_ismine, const std::optional<std::string>& filter_label,
|
Vec& ret, const std::optional<std::string>& filter_label,
|
||||||
bool include_change = false)
|
bool include_change = false)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||||
{
|
{
|
||||||
@@ -315,7 +311,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
|
|||||||
std::list<COutputEntry> listReceived;
|
std::list<COutputEntry> listReceived;
|
||||||
std::list<COutputEntry> listSent;
|
std::list<COutputEntry> listSent;
|
||||||
|
|
||||||
CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine, include_change);
|
CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, include_change);
|
||||||
|
|
||||||
// Sent
|
// Sent
|
||||||
if (!filter_label.has_value())
|
if (!filter_label.has_value())
|
||||||
@@ -484,7 +480,6 @@ RPCHelpMan listtransactions()
|
|||||||
int nFrom = 0;
|
int nFrom = 0;
|
||||||
if (!request.params[2].isNull())
|
if (!request.params[2].isNull())
|
||||||
nFrom = request.params[2].getInt<int>();
|
nFrom = request.params[2].getInt<int>();
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
|
||||||
|
|
||||||
if (nCount < 0)
|
if (nCount < 0)
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
|
||||||
@@ -501,7 +496,7 @@ RPCHelpMan listtransactions()
|
|||||||
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
|
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
|
||||||
{
|
{
|
||||||
CWalletTx *const pwtx = (*it).second;
|
CWalletTx *const pwtx = (*it).second;
|
||||||
ListTransactions(*pwallet, *pwtx, 0, true, ret, filter, filter_label);
|
ListTransactions(*pwallet, *pwtx, 0, true, ret, filter_label);
|
||||||
if ((int)ret.size() >= (nCount+nFrom)) break;
|
if ((int)ret.size() >= (nCount+nFrom)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,7 +584,6 @@ RPCHelpMan listsinceblock()
|
|||||||
std::optional<int> height; // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
|
std::optional<int> height; // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
|
||||||
std::optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
|
std::optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
|
||||||
int target_confirms = 1;
|
int target_confirms = 1;
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
|
||||||
|
|
||||||
uint256 blockId;
|
uint256 blockId;
|
||||||
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
|
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
|
||||||
@@ -623,7 +617,7 @@ RPCHelpMan listsinceblock()
|
|||||||
for (const auto& [_, tx] : wallet.mapWallet) {
|
for (const auto& [_, tx] : wallet.mapWallet) {
|
||||||
|
|
||||||
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
|
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
|
||||||
ListTransactions(wallet, tx, 0, true, transactions, filter, filter_label, include_change);
|
ListTransactions(wallet, tx, 0, true, transactions, filter_label, include_change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +634,7 @@ RPCHelpMan listsinceblock()
|
|||||||
if (it != wallet.mapWallet.end()) {
|
if (it != wallet.mapWallet.end()) {
|
||||||
// We want all transactions regardless of confirmation count to appear here,
|
// We want all transactions regardless of confirmation count to appear here,
|
||||||
// even negative confirmation ones, hence the big negative.
|
// even negative confirmation ones, hence the big negative.
|
||||||
ListTransactions(wallet, it->second, -100000000, true, removed, filter, filter_label, include_change);
|
ListTransactions(wallet, it->second, -100000000, true, removed, filter_label, include_change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blockId = block.hashPrevBlock;
|
blockId = block.hashPrevBlock;
|
||||||
@@ -730,8 +724,6 @@ RPCHelpMan gettransaction()
|
|||||||
|
|
||||||
Txid hash{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
|
Txid hash{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
|
||||||
|
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
|
||||||
|
|
||||||
bool verbose = request.params[2].isNull() ? false : request.params[2].get_bool();
|
bool verbose = request.params[2].isNull() ? false : request.params[2].get_bool();
|
||||||
|
|
||||||
UniValue entry(UniValue::VOBJ);
|
UniValue entry(UniValue::VOBJ);
|
||||||
@@ -741,19 +733,19 @@ RPCHelpMan gettransaction()
|
|||||||
}
|
}
|
||||||
const CWalletTx& wtx = it->second;
|
const CWalletTx& wtx = it->second;
|
||||||
|
|
||||||
CAmount nCredit = CachedTxGetCredit(*pwallet, wtx, filter, /*avoid_reuse=*/false);
|
CAmount nCredit = CachedTxGetCredit(*pwallet, wtx, /*avoid_reuse=*/false);
|
||||||
CAmount nDebit = CachedTxGetDebit(*pwallet, wtx, filter, /*avoid_reuse=*/false);
|
CAmount nDebit = CachedTxGetDebit(*pwallet, wtx, /*avoid_reuse=*/false);
|
||||||
CAmount nNet = nCredit - nDebit;
|
CAmount nNet = nCredit - nDebit;
|
||||||
CAmount nFee = (CachedTxIsFromMe(*pwallet, wtx, filter) ? wtx.tx->GetValueOut() - nDebit : 0);
|
CAmount nFee = (CachedTxIsFromMe(*pwallet, wtx) ? wtx.tx->GetValueOut() - nDebit : 0);
|
||||||
|
|
||||||
entry.pushKV("amount", ValueFromAmount(nNet - nFee));
|
entry.pushKV("amount", ValueFromAmount(nNet - nFee));
|
||||||
if (CachedTxIsFromMe(*pwallet, wtx, filter))
|
if (CachedTxIsFromMe(*pwallet, wtx))
|
||||||
entry.pushKV("fee", ValueFromAmount(nFee));
|
entry.pushKV("fee", ValueFromAmount(nFee));
|
||||||
|
|
||||||
WalletTxToJSON(*pwallet, wtx, entry);
|
WalletTxToJSON(*pwallet, wtx, entry);
|
||||||
|
|
||||||
UniValue details(UniValue::VARR);
|
UniValue details(UniValue::VARR);
|
||||||
ListTransactions(*pwallet, wtx, 0, false, details, filter, /*filter_label=*/std::nullopt);
|
ListTransactions(*pwallet, wtx, 0, false, details, /*filter_label=*/std::nullopt);
|
||||||
entry.pushKV("details", std::move(details));
|
entry.pushKV("details", std::move(details));
|
||||||
|
|
||||||
entry.pushKV("hex", EncodeHexTx(*wtx.tx));
|
entry.pushKV("hex", EncodeHexTx(*wtx.tx));
|
||||||
|
|||||||
@@ -525,8 +525,6 @@ RPCHelpMan simulaterawtransaction()
|
|||||||
|
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
|
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
|
||||||
|
|
||||||
const auto& txs = request.params[0].get_array();
|
const auto& txs = request.params[0].get_array();
|
||||||
CAmount changes{0};
|
CAmount changes{0};
|
||||||
std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
|
std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
|
||||||
@@ -559,7 +557,7 @@ RPCHelpMan simulaterawtransaction()
|
|||||||
if (coins.at(outpoint).IsSpent()) {
|
if (coins.at(outpoint).IsSpent()) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
|
||||||
}
|
}
|
||||||
changes -= wallet.GetDebit(txin, filter);
|
changes -= wallet.GetDebit(txin);
|
||||||
}
|
}
|
||||||
spent.insert(outpoint);
|
spent.insert(outpoint);
|
||||||
}
|
}
|
||||||
@@ -572,7 +570,7 @@ RPCHelpMan simulaterawtransaction()
|
|||||||
const auto& hash = mtx.GetHash();
|
const auto& hash = mtx.GetHash();
|
||||||
for (size_t i = 0; i < mtx.vout.size(); ++i) {
|
for (size_t i = 0; i < mtx.vout.size(); ++i) {
|
||||||
const auto& txout = mtx.vout[i];
|
const auto& txout = mtx.vout[i];
|
||||||
bool is_mine = 0 < (wallet.IsMine(txout) & filter);
|
bool is_mine = wallet.IsMine(txout);
|
||||||
changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
|
changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,15 +197,15 @@ IsMineResult LegacyWalletIsMineInnerDONOTUSE(const LegacyDataSPKM& keystore, con
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
isminetype LegacyDataSPKM::IsMine(const CScript& script) const
|
bool LegacyDataSPKM::IsMine(const CScript& script) const
|
||||||
{
|
{
|
||||||
switch (LegacyWalletIsMineInnerDONOTUSE(*this, script, IsMineSigVersion::TOP)) {
|
switch (LegacyWalletIsMineInnerDONOTUSE(*this, script, IsMineSigVersion::TOP)) {
|
||||||
case IsMineResult::INVALID:
|
case IsMineResult::INVALID:
|
||||||
case IsMineResult::NO:
|
case IsMineResult::NO:
|
||||||
return ISMINE_NO;
|
return false;
|
||||||
case IsMineResult::WATCH_ONLY:
|
case IsMineResult::WATCH_ONLY:
|
||||||
case IsMineResult::SPENDABLE:
|
case IsMineResult::SPENDABLE:
|
||||||
return ISMINE_SPENDABLE;
|
return true;
|
||||||
}
|
}
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
@@ -506,12 +506,12 @@ std::unordered_set<CScript, SaltedSipHasher> LegacyDataSPKM::GetCandidateScriptP
|
|||||||
|
|
||||||
std::unordered_set<CScript, SaltedSipHasher> LegacyDataSPKM::GetScriptPubKeys() const
|
std::unordered_set<CScript, SaltedSipHasher> LegacyDataSPKM::GetScriptPubKeys() const
|
||||||
{
|
{
|
||||||
// Run IsMine() on each candidate output script. Any script that is not ISMINE_NO is an output
|
// Run IsMine() on each candidate output script. Any script that IsMine is an output
|
||||||
// script to return.
|
// script to return.
|
||||||
// This both filters out things that are not watched by the wallet, and things that are invalid.
|
// This both filters out things that are not watched by the wallet, and things that are invalid.
|
||||||
std::unordered_set<CScript, SaltedSipHasher> spks;
|
std::unordered_set<CScript, SaltedSipHasher> spks;
|
||||||
for (const CScript& script : GetCandidateScriptPubKeys()) {
|
for (const CScript& script : GetCandidateScriptPubKeys()) {
|
||||||
if (IsMine(script) != ISMINE_NO) {
|
if (IsMine(script)) {
|
||||||
spks.insert(script);
|
spks.insert(script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,7 +524,7 @@ std::unordered_set<CScript, SaltedSipHasher> LegacyDataSPKM::GetNotMineScriptPub
|
|||||||
LOCK(cs_KeyStore);
|
LOCK(cs_KeyStore);
|
||||||
std::unordered_set<CScript, SaltedSipHasher> spks;
|
std::unordered_set<CScript, SaltedSipHasher> spks;
|
||||||
for (const CScript& script : setWatchOnly) {
|
for (const CScript& script : setWatchOnly) {
|
||||||
if (IsMine(script) == ISMINE_NO) spks.insert(script);
|
if (!IsMine(script)) spks.insert(script);
|
||||||
}
|
}
|
||||||
return spks;
|
return spks;
|
||||||
}
|
}
|
||||||
@@ -612,7 +612,7 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
|
|||||||
for (const CScript& spk : desc_spks) {
|
for (const CScript& spk : desc_spks) {
|
||||||
size_t erased = spks.erase(spk);
|
size_t erased = spks.erase(spk);
|
||||||
assert(erased == 1);
|
assert(erased == 1);
|
||||||
assert(IsMine(spk) == ISMINE_SPENDABLE);
|
assert(IsMine(spk));
|
||||||
}
|
}
|
||||||
|
|
||||||
out.desc_spkms.push_back(std::move(desc_spk_man));
|
out.desc_spkms.push_back(std::move(desc_spk_man));
|
||||||
@@ -661,7 +661,7 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
|
|||||||
for (const CScript& spk : desc_spks) {
|
for (const CScript& spk : desc_spks) {
|
||||||
size_t erased = spks.erase(spk);
|
size_t erased = spks.erase(spk);
|
||||||
assert(erased == 1);
|
assert(erased == 1);
|
||||||
assert(IsMine(spk) == ISMINE_SPENDABLE);
|
assert(IsMine(spk));
|
||||||
}
|
}
|
||||||
|
|
||||||
out.desc_spkms.push_back(std::move(desc_spk_man));
|
out.desc_spkms.push_back(std::move(desc_spk_man));
|
||||||
@@ -748,7 +748,7 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
|
|||||||
for (const CScript& desc_spk : desc_spks) {
|
for (const CScript& desc_spk : desc_spks) {
|
||||||
auto del_it = spks.find(desc_spk);
|
auto del_it = spks.find(desc_spk);
|
||||||
assert(del_it != spks.end());
|
assert(del_it != spks.end());
|
||||||
assert(IsMine(desc_spk) != ISMINE_NO);
|
assert(IsMine(desc_spk));
|
||||||
it = spks.erase(del_it);
|
it = spks.erase(del_it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -762,14 +762,14 @@ std::optional<MigrationData> LegacyDataSPKM::MigrateToDescriptor()
|
|||||||
// Legacy wallets can also contain scripts whose P2SH, P2WSH, or P2SH-P2WSH it is not watching for
|
// Legacy wallets can also contain scripts whose P2SH, P2WSH, or P2SH-P2WSH it is not watching for
|
||||||
// but can provide script data to a PSBT spending them. These "solvable" output scripts will need to
|
// but can provide script data to a PSBT spending them. These "solvable" output scripts will need to
|
||||||
// be put into the separate "solvables" wallet.
|
// be put into the separate "solvables" wallet.
|
||||||
// These can be detected by going through the entire candidate output scripts, finding the ISMINE_NO scripts,
|
// These can be detected by going through the entire candidate output scripts, finding the not IsMine scripts,
|
||||||
// and checking CanProvide() which will dummy sign.
|
// and checking CanProvide() which will dummy sign.
|
||||||
for (const CScript& script : GetCandidateScriptPubKeys()) {
|
for (const CScript& script : GetCandidateScriptPubKeys()) {
|
||||||
// Since we only care about P2SH, P2WSH, and P2SH-P2WSH, filter out any scripts that are not those
|
// Since we only care about P2SH, P2WSH, and P2SH-P2WSH, filter out any scripts that are not those
|
||||||
if (!script.IsPayToScriptHash() && !script.IsPayToWitnessScriptHash()) {
|
if (!script.IsPayToScriptHash() && !script.IsPayToWitnessScriptHash()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (IsMine(script) != ISMINE_NO) {
|
if (IsMine(script)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SignatureData dummy_sigdata;
|
SignatureData dummy_sigdata;
|
||||||
@@ -861,13 +861,10 @@ util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetNewDestination(const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype DescriptorScriptPubKeyMan::IsMine(const CScript& script) const
|
bool DescriptorScriptPubKeyMan::IsMine(const CScript& script) const
|
||||||
{
|
{
|
||||||
LOCK(cs_desc_man);
|
LOCK(cs_desc_man);
|
||||||
if (m_map_script_pub_keys.count(script) > 0) {
|
return m_map_script_pub_keys.contains(script);
|
||||||
return ISMINE_SPENDABLE;
|
|
||||||
}
|
|
||||||
return ISMINE_NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key)
|
bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key)
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
|
explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
|
||||||
virtual ~ScriptPubKeyMan() = default;
|
virtual ~ScriptPubKeyMan() = default;
|
||||||
virtual util::Result<CTxDestination> GetNewDestination(const OutputType type) { return util::Error{Untranslated("Not supported")}; }
|
virtual util::Result<CTxDestination> GetNewDestination(const OutputType type) { return util::Error{Untranslated("Not supported")}; }
|
||||||
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
|
virtual bool IsMine(const CScript& script) const { return false; }
|
||||||
|
|
||||||
//! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it.
|
//! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it.
|
||||||
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key) { return false; }
|
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key) { return false; }
|
||||||
@@ -197,7 +197,7 @@ private:
|
|||||||
// Used only in migration.
|
// Used only in migration.
|
||||||
std::unordered_set<CScript, SaltedSipHasher> GetCandidateScriptPubKeys() const;
|
std::unordered_set<CScript, SaltedSipHasher> GetCandidateScriptPubKeys() const;
|
||||||
|
|
||||||
isminetype IsMine(const CScript& script) const override;
|
bool IsMine(const CScript& script) const override;
|
||||||
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
|
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
|
||||||
public:
|
public:
|
||||||
using ScriptPubKeyMan::ScriptPubKeyMan;
|
using ScriptPubKeyMan::ScriptPubKeyMan;
|
||||||
@@ -324,7 +324,7 @@ public:
|
|||||||
mutable RecursiveMutex cs_desc_man;
|
mutable RecursiveMutex cs_desc_man;
|
||||||
|
|
||||||
util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
|
util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
|
||||||
isminetype IsMine(const CScript& script) const override;
|
bool IsMine(const CScript& script) const override;
|
||||||
|
|
||||||
bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
|
bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
|
||||||
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
||||||
|
|||||||
@@ -437,14 +437,11 @@ CoinsResult AvailableCoins(const CWallet& wallet,
|
|||||||
if (wallet.IsSpent(outpoint))
|
if (wallet.IsSpent(outpoint))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
isminetype mine = wallet.IsMine(output);
|
|
||||||
assert(mine != ISMINE_NO);
|
|
||||||
|
|
||||||
if (!allow_used_addresses && wallet.IsSpentKey(output.scriptPubKey)) {
|
if (!allow_used_addresses && wallet.IsSpentKey(output.scriptPubKey)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tx_from_me = CachedTxIsFromMe(wallet, wtx, ISMINE_ALL);
|
bool tx_from_me = CachedTxIsFromMe(wallet, wtx);
|
||||||
|
|
||||||
std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);
|
std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);
|
||||||
|
|
||||||
|
|||||||
@@ -124,15 +124,14 @@ FUZZ_TARGET(scriptpubkeyman, .init = initialize_spkm)
|
|||||||
fuzzed_data_provider,
|
fuzzed_data_provider,
|
||||||
[&] {
|
[&] {
|
||||||
const CScript script{ConsumeScript(fuzzed_data_provider)};
|
const CScript script{ConsumeScript(fuzzed_data_provider)};
|
||||||
auto is_mine{spk_manager->IsMine(script)};
|
if (spk_manager->IsMine(script)) {
|
||||||
if (is_mine == isminetype::ISMINE_SPENDABLE) {
|
|
||||||
assert(spk_manager->GetScriptPubKeys().count(script));
|
assert(spk_manager->GetScriptPubKeys().count(script));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&] {
|
[&] {
|
||||||
auto spks{spk_manager->GetScriptPubKeys()};
|
auto spks{spk_manager->GetScriptPubKeys()};
|
||||||
for (const CScript& spk : spks) {
|
for (const CScript& spk : spks) {
|
||||||
assert(spk_manager->IsMine(spk) == ISMINE_SPENDABLE);
|
assert(spk_manager->IsMine(spk));
|
||||||
CTxDestination dest;
|
CTxDestination dest;
|
||||||
bool extract_dest{ExtractDestination(spk, dest)};
|
bool extract_dest{ExtractDestination(spk, dest)};
|
||||||
if (extract_dest) {
|
if (extract_dest) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
|
std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
|
||||||
|
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
isminetype result;
|
bool result;
|
||||||
|
|
||||||
// P2PK compressed - Descriptor
|
// P2PK compressed - Descriptor
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
|
scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2PK uncompressed - Descriptor
|
// P2PK uncompressed - Descriptor
|
||||||
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
|
scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2PKH compressed - Descriptor
|
// P2PKH compressed - Descriptor
|
||||||
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
|
scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2PKH uncompressed - Descriptor
|
// P2PKH uncompressed - Descriptor
|
||||||
@@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
|
scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2SH - Descriptor
|
// P2SH - Descriptor
|
||||||
@@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
|
CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
|
// (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
|
||||||
@@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2WPKH uncompressed (invalid) - Descriptor
|
// P2WPKH uncompressed (invalid) - Descriptor
|
||||||
@@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2SH multisig - Descriptor
|
// P2SH multisig - Descriptor
|
||||||
@@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2WSH multisig with compressed keys - Descriptor
|
// P2WSH multisig with compressed keys - Descriptor
|
||||||
@@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
|
CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
|
||||||
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript));
|
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2WSH multisig with uncompressed key (invalid) - Descriptor
|
// P2WSH multisig with uncompressed key (invalid) - Descriptor
|
||||||
@@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combo - Descriptor
|
// Combo - Descriptor
|
||||||
@@ -229,28 +229,28 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
|
|
||||||
// Test P2PK
|
// Test P2PK
|
||||||
result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0]));
|
result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0]));
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
|
|
||||||
// Test P2PKH
|
// Test P2PKH
|
||||||
result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
|
result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0])));
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
|
|
||||||
// Test P2SH (combo descriptor does not describe P2SH)
|
// Test P2SH (combo descriptor does not describe P2SH)
|
||||||
CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
|
CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
BOOST_CHECK(!result);
|
||||||
|
|
||||||
// Test P2WPKH
|
// Test P2WPKH
|
||||||
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
|
|
||||||
// P2SH-P2WPKH output
|
// P2SH-P2WPKH output
|
||||||
redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
||||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
|
|
||||||
// Test P2TR (combo descriptor does not describe P2TR)
|
// Test P2TR (combo descriptor does not describe P2TR)
|
||||||
XOnlyPubKey xpk(pubkeys[0]);
|
XOnlyPubKey xpk(pubkeys[0]);
|
||||||
@@ -260,7 +260,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
WitnessV1Taproot output = builder.GetOutput();
|
WitnessV1Taproot output = builder.GetOutput();
|
||||||
scriptPubKey = GetScriptForDestination(output);
|
scriptPubKey = GetScriptForDestination(output);
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
BOOST_CHECK(!result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Taproot - Descriptor
|
// Taproot - Descriptor
|
||||||
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
|||||||
WitnessV1Taproot output = builder.GetOutput();
|
WitnessV1Taproot output = builder.GetOutput();
|
||||||
scriptPubKey = GetScriptForDestination(output);
|
scriptPubKey = GetScriptForDestination(output);
|
||||||
result = spk_manager->IsMine(scriptPubKey);
|
result = spk_manager->IsMine(scriptPubKey);
|
||||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
BOOST_CHECK(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -388,13 +388,11 @@ class WalletTXO
|
|||||||
private:
|
private:
|
||||||
const CWalletTx& m_wtx;
|
const CWalletTx& m_wtx;
|
||||||
const CTxOut& m_output;
|
const CTxOut& m_output;
|
||||||
isminetype m_ismine;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WalletTXO(const CWalletTx& wtx, const CTxOut& output, const isminetype ismine)
|
WalletTXO(const CWalletTx& wtx, const CTxOut& output)
|
||||||
: m_wtx(wtx),
|
: m_wtx(wtx),
|
||||||
m_output(output),
|
m_output(output)
|
||||||
m_ismine(ismine)
|
|
||||||
{
|
{
|
||||||
Assume(std::ranges::find(wtx.tx->vout, output) != wtx.tx->vout.end());
|
Assume(std::ranges::find(wtx.tx->vout, output) != wtx.tx->vout.end());
|
||||||
}
|
}
|
||||||
@@ -402,9 +400,6 @@ public:
|
|||||||
const CWalletTx& GetWalletTx() const { return m_wtx; }
|
const CWalletTx& GetWalletTx() const { return m_wtx; }
|
||||||
|
|
||||||
const CTxOut& GetTxOut() const { return m_output; }
|
const CTxOut& GetTxOut() const { return m_output; }
|
||||||
|
|
||||||
isminetype GetIsMine() const { return m_ismine; }
|
|
||||||
void SetIsMine(isminetype ismine) { m_ismine = ismine; }
|
|
||||||
};
|
};
|
||||||
} // namespace wallet
|
} // namespace wallet
|
||||||
|
|
||||||
|
|||||||
@@ -17,32 +17,6 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace wallet {
|
namespace wallet {
|
||||||
/**
|
|
||||||
* IsMine() return codes, which depend on ScriptPubKeyMan implementation.
|
|
||||||
* Not every ScriptPubKeyMan covers all types, please refer to
|
|
||||||
* https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.21.0.md#ismine-semantics
|
|
||||||
* for better understanding.
|
|
||||||
*
|
|
||||||
* For LegacyScriptPubKeyMan,
|
|
||||||
* ISMINE_NO: the scriptPubKey is not in the wallet;
|
|
||||||
* ISMINE_SPENDABLE: the scriptPubKey corresponds to an address owned by the wallet user (can spend with the private key);
|
|
||||||
* ISMINE_ALL: all ISMINE flags except for USED;
|
|
||||||
* ISMINE_ENUM_ELEMENTS: the number of isminetype enum elements.
|
|
||||||
*
|
|
||||||
* For DescriptorScriptPubKeyMan and future ScriptPubKeyMan,
|
|
||||||
* ISMINE_NO: the scriptPubKey is not in the wallet;
|
|
||||||
* ISMINE_SPENDABLE: the scriptPubKey matches a scriptPubKey in the wallet.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum isminetype : unsigned int {
|
|
||||||
ISMINE_NO = 0,
|
|
||||||
ISMINE_SPENDABLE = 1 << 1,
|
|
||||||
ISMINE_ALL = ISMINE_SPENDABLE,
|
|
||||||
ISMINE_ENUM_ELEMENTS,
|
|
||||||
};
|
|
||||||
/** used for bitflags of isminetype */
|
|
||||||
using isminefilter = std::underlying_type_t<isminetype>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address purpose field that has been been stored with wallet sending and
|
* Address purpose field that has been been stored with wallet sending and
|
||||||
* receiving addresses since BIP70 payment protocol support was added in
|
* receiving addresses since BIP70 payment protocol support was added in
|
||||||
|
|||||||
@@ -1569,45 +1569,45 @@ void CWallet::BlockUntilSyncedToCurrentChain() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note that this function doesn't distinguish between a 0-valued input,
|
// Note that this function doesn't distinguish between a 0-valued input,
|
||||||
// and a not-"is mine" (according to the filter) input.
|
// and a not-"is mine" input.
|
||||||
CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
CAmount CWallet::GetDebit(const CTxIn &txin) const
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
auto txo = GetTXO(txin.prevout);
|
auto txo = GetTXO(txin.prevout);
|
||||||
if (txo && (txo->GetIsMine() & filter)) {
|
if (txo) {
|
||||||
return txo->GetTxOut().nValue;
|
return txo->GetTxOut().nValue;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype CWallet::IsMine(const CTxOut& txout) const
|
bool CWallet::IsMine(const CTxOut& txout) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
return IsMine(txout.scriptPubKey);
|
return IsMine(txout.scriptPubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype CWallet::IsMine(const CTxDestination& dest) const
|
bool CWallet::IsMine(const CTxDestination& dest) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
return IsMine(GetScriptForDestination(dest));
|
return IsMine(GetScriptForDestination(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype CWallet::IsMine(const CScript& script) const
|
bool CWallet::IsMine(const CScript& script) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
|
|
||||||
// Search the cache so that IsMine is called only on the relevant SPKMs instead of on everything in m_spk_managers
|
// Search the cache so that IsMine is called only on the relevant SPKMs instead of on everything in m_spk_managers
|
||||||
const auto& it = m_cached_spks.find(script);
|
const auto& it = m_cached_spks.find(script);
|
||||||
if (it != m_cached_spks.end()) {
|
if (it != m_cached_spks.end()) {
|
||||||
isminetype res = ISMINE_NO;
|
bool res = false;
|
||||||
for (const auto& spkm : it->second) {
|
for (const auto& spkm : it->second) {
|
||||||
res = std::max(res, spkm->IsMine(script));
|
res = res || spkm->IsMine(script);
|
||||||
}
|
}
|
||||||
Assume(res == ISMINE_SPENDABLE);
|
Assume(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ISMINE_NO;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::IsMine(const CTransaction& tx) const
|
bool CWallet::IsMine(const CTransaction& tx) const
|
||||||
@@ -1619,30 +1619,30 @@ bool CWallet::IsMine(const CTransaction& tx) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype CWallet::IsMine(const COutPoint& outpoint) const
|
bool CWallet::IsMine(const COutPoint& outpoint) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
auto wtx = GetWalletTx(outpoint.hash);
|
auto wtx = GetWalletTx(outpoint.hash);
|
||||||
if (!wtx) {
|
if (!wtx) {
|
||||||
return ISMINE_NO;
|
return false;
|
||||||
}
|
}
|
||||||
if (outpoint.n >= wtx->tx->vout.size()) {
|
if (outpoint.n >= wtx->tx->vout.size()) {
|
||||||
return ISMINE_NO;
|
return false;
|
||||||
}
|
}
|
||||||
return IsMine(wtx->tx->vout[outpoint.n]);
|
return IsMine(wtx->tx->vout[outpoint.n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::IsFromMe(const CTransaction& tx) const
|
bool CWallet::IsFromMe(const CTransaction& tx) const
|
||||||
{
|
{
|
||||||
return (GetDebit(tx, ISMINE_ALL) > 0);
|
return (GetDebit(tx) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
|
CAmount CWallet::GetDebit(const CTransaction& tx) const
|
||||||
{
|
{
|
||||||
CAmount nDebit = 0;
|
CAmount nDebit = 0;
|
||||||
for (const CTxIn& txin : tx.vin)
|
for (const CTxIn& txin : tx.vin)
|
||||||
{
|
{
|
||||||
nDebit += GetDebit(txin, filter);
|
nDebit += GetDebit(txin);
|
||||||
if (!MoneyRange(nDebit))
|
if (!MoneyRange(nDebit))
|
||||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||||
}
|
}
|
||||||
@@ -2377,7 +2377,7 @@ bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& add
|
|||||||
|
|
||||||
CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
|
CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
|
||||||
record.SetLabel(strName);
|
record.SetLabel(strName);
|
||||||
is_mine = IsMine(address) != ISMINE_NO;
|
is_mine = IsMine(address);
|
||||||
if (new_purpose) { /* update purpose only if requested */
|
if (new_purpose) { /* update purpose only if requested */
|
||||||
record.purpose = new_purpose;
|
record.purpose = new_purpose;
|
||||||
}
|
}
|
||||||
@@ -4444,15 +4444,11 @@ void CWallet::RefreshTXOsFromTx(const CWalletTx& wtx)
|
|||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
for (uint32_t i = 0; i < wtx.tx->vout.size(); ++i) {
|
for (uint32_t i = 0; i < wtx.tx->vout.size(); ++i) {
|
||||||
const CTxOut& txout = wtx.tx->vout.at(i);
|
const CTxOut& txout = wtx.tx->vout.at(i);
|
||||||
isminetype ismine = IsMine(txout);
|
if (!IsMine(txout)) continue;
|
||||||
if (ismine == ISMINE_NO) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
COutPoint outpoint(wtx.GetHash(), i);
|
COutPoint outpoint(wtx.GetHash(), i);
|
||||||
if (m_txos.contains(outpoint)) {
|
if (m_txos.contains(outpoint)) {
|
||||||
m_txos.at(outpoint).SetIsMine(ismine);
|
|
||||||
} else {
|
} else {
|
||||||
m_txos.emplace(outpoint, WalletTXO{wtx, txout, ismine});
|
m_txos.emplace(outpoint, WalletTXO{wtx, txout});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -786,19 +786,16 @@ public:
|
|||||||
util::Result<CTxDestination> GetNewDestination(const OutputType type, const std::string label);
|
util::Result<CTxDestination> GetNewDestination(const OutputType type, const std::string label);
|
||||||
util::Result<CTxDestination> GetNewChangeDestination(const OutputType type);
|
util::Result<CTxDestination> GetNewChangeDestination(const OutputType type);
|
||||||
|
|
||||||
isminetype IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
isminetype IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
/**
|
/** Returns amount of debit, i.e. the amount leaving this wallet due to this input */
|
||||||
* Returns amount of debit if the input matches the
|
CAmount GetDebit(const CTxIn& txin) const;
|
||||||
* filter, otherwise returns 0
|
bool IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
*/
|
|
||||||
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
|
|
||||||
isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
|
||||||
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
isminetype IsMine(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool IsMine(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
/** should probably be renamed to IsRelevantToMe */
|
/** should probably be renamed to IsRelevantToMe */
|
||||||
bool IsFromMe(const CTransaction& tx) const;
|
bool IsFromMe(const CTransaction& tx) const;
|
||||||
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
|
CAmount GetDebit(const CTransaction& tx) const;
|
||||||
|
|
||||||
DBErrors LoadWallet();
|
DBErrors LoadWallet();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user