wallet: Use wallet's TXO set in AvailableCoins
Instead of iterating every transaction and every output stored in wallet when trying to figure out what outputs can be spent, iterate the TXO set which should be a lot smaller.
This commit is contained in:
1 parent
dde7cbe105
commit
c1801b78f1
1 file changed
+25
-16
+25
-16
@@ -330,15 +330,25 @@ CoinsResult AvailableCoins(const CWallet& wallet,
|
|||||||
std::vector<COutPoint> outpoints;
|
std::vector<COutPoint> outpoints;
|
||||||
|
|
||||||
std::set<Txid> trusted_parents;
|
std::set<Txid> trusted_parents;
|
||||||
for (const auto& entry : wallet.mapWallet)
|
// Cache for whether each tx passes the tx level checks (first bool), and whether the transaction is "safe" (second bool)
|
||||||
{
|
std::unordered_map<uint256, std::pair<bool, bool>, SaltedTxidHasher> tx_safe_cache;
|
||||||
const Txid& txid = entry.first;
|
for (const auto& [outpoint, txo] : wallet.GetTXOs()) {
|
||||||
const CWalletTx& wtx = entry.second;
|
const CWalletTx& wtx = txo.GetWalletTx();
|
||||||
|
const CTxOut& output = txo.GetTxOut();
|
||||||
|
|
||||||
|
if (tx_safe_cache.contains(outpoint.hash) && !tx_safe_cache.at(outpoint.hash).first) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nDepth = wallet.GetTxDepthInMainChain(wtx);
|
||||||
|
|
||||||
|
// Perform tx level checks if we haven't already come across outputs from this tx before.
|
||||||
|
if (!tx_safe_cache.contains(outpoint.hash)) {
|
||||||
|
tx_safe_cache[outpoint.hash] = {false, false};
|
||||||
|
|
||||||
if (wallet.IsTxImmatureCoinBase(wtx) && !params.include_immature_coinbase)
|
if (wallet.IsTxImmatureCoinBase(wtx) && !params.include_immature_coinbase)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int nDepth = wallet.GetTxDepthInMainChain(wtx);
|
|
||||||
if (nDepth < 0)
|
if (nDepth < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -388,11 +398,12 @@ CoinsResult AvailableCoins(const CWallet& wallet,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tx_from_me = CachedTxIsFromMe(wallet, wtx, ISMINE_ALL);
|
tx_safe_cache[outpoint.hash] = {true, safeTx};
|
||||||
|
}
|
||||||
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
|
const auto& [tx_ok, tx_safe] = tx_safe_cache.at(outpoint.hash);
|
||||||
const CTxOut& output = wtx.tx->vout[i];
|
if (!Assume(tx_ok)) {
|
||||||
const COutPoint outpoint(txid, i);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (output.nValue < params.min_amount || output.nValue > params.max_amount)
|
if (output.nValue < params.min_amount || output.nValue > params.max_amount)
|
||||||
continue;
|
continue;
|
||||||
@@ -408,15 +419,14 @@ CoinsResult AvailableCoins(const CWallet& wallet,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
isminetype mine = wallet.IsMine(output);
|
isminetype mine = wallet.IsMine(output);
|
||||||
|
assert(mine != ISMINE_NO);
|
||||||
if (mine == ISMINE_NO) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);
|
std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);
|
||||||
|
|
||||||
int input_bytes = CalculateMaximumSignedInputSize(output, COutPoint(), provider.get(), can_grind_r, coinControl);
|
int input_bytes = CalculateMaximumSignedInputSize(output, COutPoint(), provider.get(), can_grind_r, coinControl);
|
||||||
@@ -445,7 +455,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.Add(GetOutputType(type, is_from_p2sh),
|
result.Add(GetOutputType(type, is_from_p2sh),
|
||||||
COutput(outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate));
|
COutput(outpoint, output, nDepth, input_bytes, spendable, solvable, tx_safe, wtx.GetTxTime(), tx_from_me, feerate));
|
||||||
|
|
||||||
outpoints.push_back(outpoint);
|
outpoints.push_back(outpoint);
|
||||||
|
|
||||||
@@ -461,7 +471,6 @@ CoinsResult AvailableCoins(const CWallet& wallet,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (feerate.has_value()) {
|
if (feerate.has_value()) {
|
||||||
std::map<COutPoint, CAmount> map_of_bump_fees = wallet.chain().calculateIndividualBumpFees(outpoints, feerate.value());
|
std::map<COutPoint, CAmount> map_of_bump_fees = wallet.chain().calculateIndividualBumpFees(outpoints, feerate.value());
|
||||||
|
|||||||
Reference in new issue
Block a user