Merge #15596: rpc: Ignore sendmany::minconf as dummy value
fabfb79673
doc: Add release notes for 15596 (MarcoFalke)fac1a0fe54
wallet: Remove unused GetLegacyBalance (MarcoFalke)faa3a246e8
scripted-diff: wallet: Rename pcoin to wtx (MarcoFalke)fae5f874d5
rpc: Document that minconf is an ignored dummy value (MarcoFalke) Pull request description: Other RPCs such as `sendtoaddress` don't have this option at all and `sendmany` should by default spend from (lets say) our change. ACKs for commit fabfb7: jnewbery: utACKfabfb79673
ryanofsky: utACKfabfb79673
. Nice writeup! Release notes are only change since previous review. Tree-SHA512: 2526ead2330be7c2beb78b96bc5e55440566c4a3a809bbbd66f5c9fc517f6890affa5d14005dc102644d49679a374510f9507255e870cf88aaa63e429beef658
This commit is contained in:
commit
daef20fb50
4 changed files with 65 additions and 102 deletions
|
@ -66,9 +66,21 @@ platform.
|
||||||
Notable changes
|
Notable changes
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Example item
|
Updated RPCs
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
Note: some low-level RPC changes mainly useful for testing are described in the
|
||||||
|
Low-level Changes section below.
|
||||||
|
|
||||||
|
* The `sendmany` RPC had an argument `minconf` that was not well specified and
|
||||||
|
would lead to RPC errors even when the wallet's coin selection would succeed.
|
||||||
|
The `sendtoaddress` RPC never had this check, so to normalize the behavior,
|
||||||
|
`minconf` is now ignored in `sendmany`. If the coin selection does not
|
||||||
|
succeed due to missing coins, it will still throw an RPC error. Be reminded
|
||||||
|
that coin selection is influenced by the `-spendzeroconfchange`,
|
||||||
|
`-limitancestorcount`, `-limitdescendantcount` and `-walletrejectlongchains`
|
||||||
|
command line arguments.
|
||||||
|
|
||||||
|
|
||||||
Low-level changes
|
Low-level changes
|
||||||
=================
|
=================
|
||||||
|
|
|
@ -807,9 +807,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
|
const RPCHelpMan help{"sendmany",
|
||||||
throw std::runtime_error(
|
|
||||||
RPCHelpMan{"sendmany",
|
|
||||||
"\nSend multiple times. Amounts are double-precision floating point numbers." +
|
"\nSend multiple times. Amounts are double-precision floating point numbers." +
|
||||||
HelpRequiringPassphrase(pwallet) + "\n",
|
HelpRequiringPassphrase(pwallet) + "\n",
|
||||||
{
|
{
|
||||||
|
@ -819,7 +817,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
|
{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{"minconf", RPCArg::Type::NUM, /* default */ "1", "Only use the balance confirmed at least this many times."},
|
{"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Ignored dummy value"},
|
||||||
{"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment"},
|
{"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment"},
|
||||||
{"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array with addresses.\n"
|
{"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array with addresses.\n"
|
||||||
" The fee will be equally deducted from the amount of each selected address.\n"
|
" The fee will be equally deducted from the amount of each selected address.\n"
|
||||||
|
@ -850,7 +848,11 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
"\nAs a JSON-RPC call\n"
|
"\nAs a JSON-RPC call\n"
|
||||||
+ HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
|
+ HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
|
||||||
},
|
},
|
||||||
}.ToString());
|
};
|
||||||
|
|
||||||
|
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
|
||||||
|
throw std::runtime_error(help.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the results are valid at least up to the most recent block
|
// Make sure the results are valid at least up to the most recent block
|
||||||
// the user could have gotten from another RPC command prior to now
|
// the user could have gotten from another RPC command prior to now
|
||||||
|
@ -867,9 +869,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");
|
||||||
}
|
}
|
||||||
UniValue sendTo = request.params[1].get_obj();
|
UniValue sendTo = request.params[1].get_obj();
|
||||||
int nMinDepth = 1;
|
|
||||||
if (!request.params[2].isNull())
|
|
||||||
nMinDepth = request.params[2].get_int();
|
|
||||||
|
|
||||||
mapValue_t mapValue;
|
mapValue_t mapValue;
|
||||||
if (!request.params[3].isNull() && !request.params[3].get_str().empty())
|
if (!request.params[3].isNull() && !request.params[3].get_str().empty())
|
||||||
|
@ -897,7 +896,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
std::set<CTxDestination> destinations;
|
std::set<CTxDestination> destinations;
|
||||||
std::vector<CRecipient> vecSend;
|
std::vector<CRecipient> vecSend;
|
||||||
|
|
||||||
CAmount totalAmount = 0;
|
|
||||||
std::vector<std::string> keys = sendTo.getKeys();
|
std::vector<std::string> keys = sendTo.getKeys();
|
||||||
for (const std::string& name_ : keys) {
|
for (const std::string& name_ : keys) {
|
||||||
CTxDestination dest = DecodeDestination(name_);
|
CTxDestination dest = DecodeDestination(name_);
|
||||||
|
@ -914,7 +912,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
CAmount nAmount = AmountFromValue(sendTo[name_]);
|
CAmount nAmount = AmountFromValue(sendTo[name_]);
|
||||||
if (nAmount <= 0)
|
if (nAmount <= 0)
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||||
totalAmount += nAmount;
|
|
||||||
|
|
||||||
bool fSubtractFeeFromAmount = false;
|
bool fSubtractFeeFromAmount = false;
|
||||||
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
|
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
|
||||||
|
@ -929,11 +926,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
|
||||||
|
|
||||||
EnsureWalletIsUnlocked(pwallet);
|
EnsureWalletIsUnlocked(pwallet);
|
||||||
|
|
||||||
// Check funds
|
|
||||||
if (totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth)) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shuffle recipient list
|
// Shuffle recipient list
|
||||||
std::shuffle(vecSend.begin(), vecSend.end(), FastRandomContext());
|
std::shuffle(vecSend.begin(), vecSend.end(), FastRandomContext());
|
||||||
|
|
||||||
|
|
|
@ -2162,9 +2162,9 @@ CAmount CWallet::GetBalance(const isminefilter& filter, const int min_depth) con
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
if (pcoin->IsTrusted(*locked_chain) && pcoin->GetDepthInMainChain(*locked_chain) >= min_depth) {
|
if (wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) >= min_depth) {
|
||||||
nTotal += pcoin->GetAvailableCredit(*locked_chain, true, filter);
|
nTotal += wtx.GetAvailableCredit(*locked_chain, true, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2180,9 +2180,9 @@ CAmount CWallet::GetUnconfirmedBalance() const
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
if (!pcoin->IsTrusted(*locked_chain) && pcoin->GetDepthInMainChain(*locked_chain) == 0 && pcoin->InMempool())
|
if (!wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) == 0 && wtx.InMempool())
|
||||||
nTotal += pcoin->GetAvailableCredit(*locked_chain);
|
nTotal += wtx.GetAvailableCredit(*locked_chain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nTotal;
|
return nTotal;
|
||||||
|
@ -2196,8 +2196,8 @@ CAmount CWallet::GetImmatureBalance() const
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
nTotal += pcoin->GetImmatureCredit(*locked_chain);
|
nTotal += wtx.GetImmatureCredit(*locked_chain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nTotal;
|
return nTotal;
|
||||||
|
@ -2211,9 +2211,9 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
if (!pcoin->IsTrusted(*locked_chain) && pcoin->GetDepthInMainChain(*locked_chain) == 0 && pcoin->InMempool())
|
if (!wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) == 0 && wtx.InMempool())
|
||||||
nTotal += pcoin->GetAvailableCredit(*locked_chain, true, ISMINE_WATCH_ONLY);
|
nTotal += wtx.GetAvailableCredit(*locked_chain, true, ISMINE_WATCH_ONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nTotal;
|
return nTotal;
|
||||||
|
@ -2227,53 +2227,13 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
nTotal += pcoin->GetImmatureWatchOnlyCredit(*locked_chain);
|
nTotal += wtx.GetImmatureWatchOnlyCredit(*locked_chain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nTotal;
|
return nTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total balance in a different way from GetBalance. The biggest
|
|
||||||
// difference is that GetBalance sums up all unspent TxOuts paying to the
|
|
||||||
// wallet, while this sums up both spent and unspent TxOuts paying to the
|
|
||||||
// wallet, and then subtracts the values of TxIns spending from the wallet. This
|
|
||||||
// also has fewer restrictions on which unconfirmed transactions are considered
|
|
||||||
// trusted.
|
|
||||||
CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) const
|
|
||||||
{
|
|
||||||
auto locked_chain = chain().lock();
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
|
|
||||||
CAmount balance = 0;
|
|
||||||
for (const auto& entry : mapWallet) {
|
|
||||||
const CWalletTx& wtx = entry.second;
|
|
||||||
const int depth = wtx.GetDepthInMainChain(*locked_chain);
|
|
||||||
if (depth < 0 || !locked_chain->checkFinalTx(*wtx.tx) || wtx.IsImmatureCoinBase(*locked_chain)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through tx outputs and add incoming payments. For outgoing txs,
|
|
||||||
// treat change outputs specially, as part of the amount debited.
|
|
||||||
CAmount debit = wtx.GetDebit(filter);
|
|
||||||
const bool outgoing = debit > 0;
|
|
||||||
for (const CTxOut& out : wtx.tx->vout) {
|
|
||||||
if (outgoing && IsChange(out)) {
|
|
||||||
debit -= out.nValue;
|
|
||||||
} else if (IsMine(out) & filter && depth >= minDepth) {
|
|
||||||
balance += out.nValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For outgoing txs, subtract amount debited.
|
|
||||||
if (outgoing) {
|
|
||||||
balance -= debit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
|
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
|
||||||
{
|
{
|
||||||
auto locked_chain = chain().lock();
|
auto locked_chain = chain().lock();
|
||||||
|
@ -2300,25 +2260,25 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
|
||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const uint256& wtxid = entry.first;
|
const uint256& wtxid = entry.first;
|
||||||
const CWalletTx* pcoin = &entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
|
|
||||||
if (!locked_chain.checkFinalTx(*pcoin->tx)) {
|
if (!locked_chain.checkFinalTx(*wtx.tx)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcoin->IsImmatureCoinBase(locked_chain))
|
if (wtx.IsImmatureCoinBase(locked_chain))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int nDepth = pcoin->GetDepthInMainChain(locked_chain);
|
int nDepth = wtx.GetDepthInMainChain(locked_chain);
|
||||||
if (nDepth < 0)
|
if (nDepth < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// We should not consider coins which aren't at least in our mempool
|
// We should not consider coins which aren't at least in our mempool
|
||||||
// It's possible for these to be conflicted via ancestors which we may never be able to detect
|
// It's possible for these to be conflicted via ancestors which we may never be able to detect
|
||||||
if (nDepth == 0 && !pcoin->InMempool())
|
if (nDepth == 0 && !wtx.InMempool())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool safeTx = pcoin->IsTrusted(locked_chain);
|
bool safeTx = wtx.IsTrusted(locked_chain);
|
||||||
|
|
||||||
// We should not consider coins from transactions that are replacing
|
// We should not consider coins from transactions that are replacing
|
||||||
// other transactions.
|
// other transactions.
|
||||||
|
@ -2335,7 +2295,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
|
||||||
// be a 1-block reorg away from the chain where transactions A and C
|
// be a 1-block reorg away from the chain where transactions A and C
|
||||||
// were accepted to another chain where B, B', and C were all
|
// were accepted to another chain where B, B', and C were all
|
||||||
// accepted.
|
// accepted.
|
||||||
if (nDepth == 0 && pcoin->mapValue.count("replaces_txid")) {
|
if (nDepth == 0 && wtx.mapValue.count("replaces_txid")) {
|
||||||
safeTx = false;
|
safeTx = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2347,7 +2307,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
|
||||||
// intending to replace A', but potentially resulting in a scenario
|
// intending to replace A', but potentially resulting in a scenario
|
||||||
// where A, A', and D could all be accepted (instead of just B and
|
// where A, A', and D could all be accepted (instead of just B and
|
||||||
// D, or just A and A' like the user would want).
|
// D, or just A and A' like the user would want).
|
||||||
if (nDepth == 0 && pcoin->mapValue.count("replaced_by_txid")) {
|
if (nDepth == 0 && wtx.mapValue.count("replaced_by_txid")) {
|
||||||
safeTx = false;
|
safeTx = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2358,8 +2318,8 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
|
||||||
if (nDepth < nMinDepth || nDepth > nMaxDepth)
|
if (nDepth < nMinDepth || nDepth > nMaxDepth)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
|
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
|
||||||
if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount)
|
if (wtx.tx->vout[i].nValue < nMinimumAmount || wtx.tx->vout[i].nValue > nMaximumAmount)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i)))
|
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i)))
|
||||||
|
@ -2371,20 +2331,20 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
|
||||||
if (IsSpent(locked_chain, wtxid, i))
|
if (IsSpent(locked_chain, wtxid, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
isminetype mine = IsMine(pcoin->tx->vout[i]);
|
isminetype mine = IsMine(wtx.tx->vout[i]);
|
||||||
|
|
||||||
if (mine == ISMINE_NO) {
|
if (mine == ISMINE_NO) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
|
bool solvable = IsSolvable(*this, wtx.tx->vout[i].scriptPubKey);
|
||||||
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
|
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
|
||||||
|
|
||||||
vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
|
vCoins.push_back(COutput(&wtx, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
|
||||||
|
|
||||||
// Checks the sum amount of all UTXO's.
|
// Checks the sum amount of all UTXO's.
|
||||||
if (nMinimumSumAmount != MAX_MONEY) {
|
if (nMinimumSumAmount != MAX_MONEY) {
|
||||||
nTotal += pcoin->tx->vout[i].nValue;
|
nTotal += wtx.tx->vout[i].nValue;
|
||||||
|
|
||||||
if (nTotal >= nMinimumSumAmount) {
|
if (nTotal >= nMinimumSumAmount) {
|
||||||
return;
|
return;
|
||||||
|
@ -2542,13 +2502,13 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
|
||||||
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
|
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
|
||||||
if (it != mapWallet.end())
|
if (it != mapWallet.end())
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &it->second;
|
const CWalletTx& wtx = it->second;
|
||||||
// Clearly invalid input, fail
|
// Clearly invalid input, fail
|
||||||
if (pcoin->tx->vout.size() <= outpoint.n)
|
if (wtx.tx->vout.size() <= outpoint.n)
|
||||||
return false;
|
return false;
|
||||||
// Just to calculate the marginal byte size
|
// Just to calculate the marginal byte size
|
||||||
nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue;
|
nValueFromPresetInputs += wtx.tx->vout[outpoint.n].nValue;
|
||||||
setPresetCoins.insert(CInputCoin(pcoin->tx, outpoint.n));
|
setPresetCoins.insert(CInputCoin(wtx.tx, outpoint.n));
|
||||||
} else
|
} else
|
||||||
return false; // TODO: Allow non-wallet inputs
|
return false; // TODO: Allow non-wallet inputs
|
||||||
}
|
}
|
||||||
|
@ -3586,27 +3546,27 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain:
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
for (const auto& walletEntry : mapWallet)
|
for (const auto& walletEntry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx *pcoin = &walletEntry.second;
|
const CWalletTx& wtx = walletEntry.second;
|
||||||
|
|
||||||
if (!pcoin->IsTrusted(locked_chain))
|
if (!wtx.IsTrusted(locked_chain))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pcoin->IsImmatureCoinBase(locked_chain))
|
if (wtx.IsImmatureCoinBase(locked_chain))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int nDepth = pcoin->GetDepthInMainChain(locked_chain);
|
int nDepth = wtx.GetDepthInMainChain(locked_chain);
|
||||||
if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
|
if (nDepth < (wtx.IsFromMe(ISMINE_ALL) ? 0 : 1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
|
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
|
||||||
{
|
{
|
||||||
CTxDestination addr;
|
CTxDestination addr;
|
||||||
if (!IsMine(pcoin->tx->vout[i]))
|
if (!IsMine(wtx.tx->vout[i]))
|
||||||
continue;
|
continue;
|
||||||
if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr))
|
if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CAmount n = IsSpent(locked_chain, walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
|
CAmount n = IsSpent(locked_chain, walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue;
|
||||||
|
|
||||||
if (!balances.count(addr))
|
if (!balances.count(addr))
|
||||||
balances[addr] = 0;
|
balances[addr] = 0;
|
||||||
|
@ -3626,13 +3586,13 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||||
|
|
||||||
for (const auto& walletEntry : mapWallet)
|
for (const auto& walletEntry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx *pcoin = &walletEntry.second;
|
const CWalletTx& wtx = walletEntry.second;
|
||||||
|
|
||||||
if (pcoin->tx->vin.size() > 0)
|
if (wtx.tx->vin.size() > 0)
|
||||||
{
|
{
|
||||||
bool any_mine = false;
|
bool any_mine = false;
|
||||||
// group all input addresses with each other
|
// group all input addresses with each other
|
||||||
for (const CTxIn& txin : pcoin->tx->vin)
|
for (const CTxIn& txin : wtx.tx->vin)
|
||||||
{
|
{
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
if(!IsMine(txin)) /* If this input isn't mine, ignore it */
|
if(!IsMine(txin)) /* If this input isn't mine, ignore it */
|
||||||
|
@ -3646,7 +3606,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||||
// group change with input addresses
|
// group change with input addresses
|
||||||
if (any_mine)
|
if (any_mine)
|
||||||
{
|
{
|
||||||
for (const CTxOut& txout : pcoin->tx->vout)
|
for (const CTxOut& txout : wtx.tx->vout)
|
||||||
if (IsChange(txout))
|
if (IsChange(txout))
|
||||||
{
|
{
|
||||||
CTxDestination txoutAddr;
|
CTxDestination txoutAddr;
|
||||||
|
@ -3663,7 +3623,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||||
}
|
}
|
||||||
|
|
||||||
// group lone addrs by themselves
|
// group lone addrs by themselves
|
||||||
for (const auto& txout : pcoin->tx->vout)
|
for (const auto& txout : wtx.tx->vout)
|
||||||
if (IsMine(txout))
|
if (IsMine(txout))
|
||||||
{
|
{
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
|
|
|
@ -952,7 +952,6 @@ public:
|
||||||
CAmount GetImmatureBalance() const;
|
CAmount GetImmatureBalance() const;
|
||||||
CAmount GetUnconfirmedWatchOnlyBalance() const;
|
CAmount GetUnconfirmedWatchOnlyBalance() const;
|
||||||
CAmount GetImmatureWatchOnlyBalance() const;
|
CAmount GetImmatureWatchOnlyBalance() const;
|
||||||
CAmount GetLegacyBalance(const isminefilter& filter, int minDepth) const;
|
|
||||||
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
|
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
|
||||||
|
|
||||||
OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend);
|
OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend);
|
||||||
|
|
Loading…
Add table
Reference in a new issue