Remove locked_chain from GetDepthInMainChain and its callers

We don't remove yet Chain locks as we need to preserve lock
order with CWallet one until swapping at once to avoid
deadlock failures (spotted by --enable-debug)
This commit is contained in:
Antoine Riard 2019-04-29 09:52:01 -04:00
parent 0ff03871ad
commit b66c429c56
7 changed files with 91 additions and 93 deletions

View File

@ -31,7 +31,7 @@ namespace interfaces {
namespace { namespace {
//! Construct wallet tx struct. //! Construct wallet tx struct.
WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, const CWalletTx& wtx) WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
{ {
WalletTx result; WalletTx result;
result.tx = wtx.tx; result.tx = wtx.tx;
@ -49,7 +49,7 @@ WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, co
wallet.IsMine(result.txout_address.back()) : wallet.IsMine(result.txout_address.back()) :
ISMINE_NO); ISMINE_NO);
} }
result.credit = wtx.GetCredit(locked_chain, ISMINE_ALL); result.credit = wtx.GetCredit(ISMINE_ALL);
result.debit = wtx.GetDebit(ISMINE_ALL); result.debit = wtx.GetDebit(ISMINE_ALL);
result.change = wtx.GetChange(); result.change = wtx.GetChange();
result.time = wtx.GetTxTime(); result.time = wtx.GetTxTime();
@ -63,21 +63,20 @@ WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const C
{ {
WalletTxStatus result; WalletTxStatus result;
result.block_height = locked_chain.getBlockHeight(wtx.m_confirm.hashBlock).get_value_or(std::numeric_limits<int>::max()); result.block_height = locked_chain.getBlockHeight(wtx.m_confirm.hashBlock).get_value_or(std::numeric_limits<int>::max());
result.blocks_to_maturity = wtx.GetBlocksToMaturity(locked_chain); result.blocks_to_maturity = wtx.GetBlocksToMaturity();
result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain); result.depth_in_main_chain = wtx.GetDepthInMainChain();
result.time_received = wtx.nTimeReceived; result.time_received = wtx.nTimeReceived;
result.lock_time = wtx.tx->nLockTime; result.lock_time = wtx.tx->nLockTime;
result.is_final = locked_chain.checkFinalTx(*wtx.tx); result.is_final = locked_chain.checkFinalTx(*wtx.tx);
result.is_trusted = wtx.IsTrusted(locked_chain); result.is_trusted = wtx.IsTrusted(locked_chain);
result.is_abandoned = wtx.isAbandoned(); result.is_abandoned = wtx.isAbandoned();
result.is_coinbase = wtx.IsCoinBase(); result.is_coinbase = wtx.IsCoinBase();
result.is_in_main_chain = wtx.IsInMainChain(locked_chain); result.is_in_main_chain = wtx.IsInMainChain();
return result; return result;
} }
//! Construct wallet TxOut struct. //! Construct wallet TxOut struct.
WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock& locked_chain, WalletTxOut MakeWalletTxOut(CWallet& wallet,
CWallet& wallet,
const CWalletTx& wtx, const CWalletTx& wtx,
int n, int n,
int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
@ -86,7 +85,7 @@ WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock& locked_chain,
result.txout = wtx.tx->vout[n]; result.txout = wtx.tx->vout[n];
result.time = wtx.GetTxTime(); result.time = wtx.GetTxTime();
result.depth_in_main_chain = depth; result.depth_in_main_chain = depth;
result.is_spent = wallet.IsSpent(locked_chain, wtx.GetHash(), n); result.is_spent = wallet.IsSpent(wtx.GetHash(), n);
return result; return result;
} }
@ -235,7 +234,7 @@ public:
{ {
auto locked_chain = m_wallet->chain().lock(); auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet); LOCK(m_wallet->cs_wallet);
return m_wallet->AbandonTransaction(*locked_chain, txid); return m_wallet->AbandonTransaction(txid);
} }
bool transactionCanBeBumped(const uint256& txid) override bool transactionCanBeBumped(const uint256& txid) override
{ {
@ -282,7 +281,7 @@ public:
LOCK(m_wallet->cs_wallet); LOCK(m_wallet->cs_wallet);
auto mi = m_wallet->mapWallet.find(txid); auto mi = m_wallet->mapWallet.find(txid);
if (mi != m_wallet->mapWallet.end()) { if (mi != m_wallet->mapWallet.end()) {
return MakeWalletTx(*locked_chain, *m_wallet, mi->second); return MakeWalletTx(*m_wallet, mi->second);
} }
return {}; return {};
} }
@ -293,7 +292,7 @@ public:
std::vector<WalletTx> result; std::vector<WalletTx> result;
result.reserve(m_wallet->mapWallet.size()); result.reserve(m_wallet->mapWallet.size());
for (const auto& entry : m_wallet->mapWallet) { for (const auto& entry : m_wallet->mapWallet) {
result.emplace_back(MakeWalletTx(*locked_chain, *m_wallet, entry.second)); result.emplace_back(MakeWalletTx(*m_wallet, entry.second));
} }
return result; return result;
} }
@ -338,7 +337,7 @@ public:
in_mempool = mi->second.InMempool(); in_mempool = mi->second.InMempool();
order_form = mi->second.vOrderForm; order_form = mi->second.vOrderForm;
tx_status = MakeWalletTxStatus(*locked_chain, mi->second); tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return MakeWalletTx(*locked_chain, *m_wallet, mi->second); return MakeWalletTx(*m_wallet, mi->second);
} }
return {}; return {};
} }
@ -407,7 +406,7 @@ public:
auto& group = result[entry.first]; auto& group = result[entry.first];
for (const auto& coin : entry.second) { for (const auto& coin : entry.second) {
group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i), group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i),
MakeWalletTxOut(*locked_chain, *m_wallet, *coin.tx, coin.i, coin.nDepth)); MakeWalletTxOut(*m_wallet, *coin.tx, coin.i, coin.nDepth));
} }
} }
return result; return result;
@ -422,9 +421,9 @@ public:
result.emplace_back(); result.emplace_back();
auto it = m_wallet->mapWallet.find(output.hash); auto it = m_wallet->mapWallet.find(output.hash);
if (it != m_wallet->mapWallet.end()) { if (it != m_wallet->mapWallet.end()) {
int depth = it->second.GetDepthInMainChain(*locked_chain); int depth = it->second.GetDepthInMainChain();
if (depth >= 0) { if (depth >= 0) {
result.back() = MakeWalletTxOut(*locked_chain, *m_wallet, it->second, output.n, depth); result.back() = MakeWalletTxOut(*m_wallet, it->second, output.n, depth);
} }
} }
} }

View File

@ -16,7 +16,7 @@
//! Check whether transaction has descendant in wallet or mempool, or has been //! Check whether transaction has descendant in wallet or mempool, or has been
//! mined, or conflicts with a mined transaction. Return a feebumper::Result. //! mined, or conflicts with a mined transaction. Return a feebumper::Result.
static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet& wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
if (wallet.HasWalletSpend(wtx.GetHash())) { if (wallet.HasWalletSpend(wtx.GetHash())) {
errors.push_back("Transaction has descendants in the wallet"); errors.push_back("Transaction has descendants in the wallet");
@ -30,7 +30,7 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai
} }
} }
if (wtx.GetDepthInMainChain(locked_chain) != 0) { if (wtx.GetDepthInMainChain() != 0) {
errors.push_back("Transaction has been mined, or is conflicted with a mined transaction"); errors.push_back("Transaction has been mined, or is conflicted with a mined transaction");
return feebumper::Result::WALLET_ERROR; return feebumper::Result::WALLET_ERROR;
} }
@ -146,7 +146,7 @@ bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid)
if (wtx == nullptr) return false; if (wtx == nullptr) return false;
std::vector<std::string> errors_dummy; std::vector<std::string> errors_dummy;
feebumper::Result res = PreconditionChecks(*locked_chain, wallet, *wtx, errors_dummy); feebumper::Result res = PreconditionChecks(wallet, *wtx, errors_dummy);
return res == feebumper::Result::OK; return res == feebumper::Result::OK;
} }
@ -165,7 +165,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co
} }
const CWalletTx& wtx = it->second; const CWalletTx& wtx = it->second;
Result result = PreconditionChecks(*locked_chain, *wallet, wtx, errors); Result result = PreconditionChecks(*wallet, wtx, errors);
if (result != Result::OK) { if (result != Result::OK) {
return result; return result;
} }
@ -291,7 +291,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
} }
const CWalletTx& wtx = it->second; const CWalletTx& wtx = it->second;
Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors); Result result = PreconditionChecks(wallet, wtx, errors);
if (result != Result::OK) { if (result != Result::OK) {
return result; return result;
} }
@ -382,7 +382,7 @@ Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransacti
CWalletTx& oldWtx = it->second; CWalletTx& oldWtx = it->second;
// make sure the transaction still has no descendants and hasn't been mined in the meantime // make sure the transaction still has no descendants and hasn't been mined in the meantime
Result result = PreconditionChecks(*locked_chain, wallet, oldWtx, errors); Result result = PreconditionChecks(wallet, oldWtx, errors);
if (result != Result::OK) { if (result != Result::OK) {
return result; return result;
} }

View File

@ -325,7 +325,7 @@ UniValue importaddress(const JSONRPCRequest& request)
{ {
auto locked_chain = pwallet->chain().lock(); auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
pwallet->ReacceptWalletTransactions(*locked_chain); pwallet->ReacceptWalletTransactions();
} }
} }
@ -514,7 +514,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
{ {
auto locked_chain = pwallet->chain().lock(); auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
pwallet->ReacceptWalletTransactions(*locked_chain); pwallet->ReacceptWalletTransactions();
} }
} }
@ -1413,7 +1413,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
{ {
auto locked_chain = pwallet->chain().lock(); auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
pwallet->ReacceptWalletTransactions(*locked_chain); pwallet->ReacceptWalletTransactions();
} }
if (pwallet->IsAbortingRescan()) { if (pwallet->IsAbortingRescan()) {

View File

@ -126,7 +126,7 @@ void EnsureWalletIsUnlocked(const CWallet* pwallet)
static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx, UniValue& entry) static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx, UniValue& entry)
{ {
int confirms = wtx.GetDepthInMainChain(locked_chain); int confirms = wtx.GetDepthInMainChain();
entry.pushKV("confirmations", confirms); entry.pushKV("confirmations", confirms);
if (wtx.IsCoinBase()) if (wtx.IsCoinBase())
entry.pushKV("generated", true); entry.pushKV("generated", true);
@ -631,7 +631,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
for (const CTxOut& txout : wtx.tx->vout) for (const CTxOut& txout : wtx.tx->vout)
if (txout.scriptPubKey == scriptPubKey) if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth) if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue; nAmount += txout.nValue;
} }
@ -697,7 +697,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{ {
CTxDestination address; CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) && pwallet->IsMine(address) && setAddress.count(address)) { if (ExtractDestination(txout.scriptPubKey, address) && pwallet->IsMine(address) && setAddress.count(address)) {
if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth) if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue; nAmount += txout.nValue;
} }
} }
@ -1057,7 +1057,7 @@ static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * co
continue; continue;
} }
int nDepth = wtx.GetDepthInMainChain(locked_chain); int nDepth = wtx.GetDepthInMainChain();
if (nDepth < nMinDepth) if (nDepth < nMinDepth)
continue; continue;
@ -1314,8 +1314,7 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con
} }
// Received // Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain(locked_chain) >= nMinDepth) if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) {
{
for (const COutputEntry& r : listReceived) for (const COutputEntry& r : listReceived)
{ {
std::string label; std::string label;
@ -1332,9 +1331,9 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con
MaybePushAddress(entry, r.destination); MaybePushAddress(entry, r.destination);
if (wtx.IsCoinBase()) if (wtx.IsCoinBase())
{ {
if (wtx.GetDepthInMainChain(locked_chain) < 1) if (wtx.GetDepthInMainChain() < 1)
entry.pushKV("category", "orphan"); entry.pushKV("category", "orphan");
else if (wtx.IsImmatureCoinBase(locked_chain)) else if (wtx.IsImmatureCoinBase())
entry.pushKV("category", "immature"); entry.pushKV("category", "immature");
else else
entry.pushKV("category", "generate"); entry.pushKV("category", "generate");
@ -1598,7 +1597,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) { for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
CWalletTx tx = pairWtx.second; CWalletTx tx = pairWtx.second;
if (depth == -1 || abs(tx.GetDepthInMainChain(*locked_chain)) < depth) { if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) {
ListTransactions(*locked_chain, pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */); ListTransactions(*locked_chain, pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
} }
} }
@ -1715,7 +1714,7 @@ static UniValue gettransaction(const JSONRPCRequest& request)
} }
const CWalletTx& wtx = it->second; const CWalletTx& wtx = it->second;
CAmount nCredit = wtx.GetCredit(*locked_chain, filter); CAmount nCredit = wtx.GetCredit(filter);
CAmount nDebit = wtx.GetDebit(filter); CAmount nDebit = wtx.GetDebit(filter);
CAmount nNet = nCredit - nDebit; CAmount nNet = nCredit - nDebit;
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0); CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
@ -1779,7 +1778,7 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
if (!pwallet->mapWallet.count(hash)) { if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
} }
if (!pwallet->AbandonTransaction(*locked_chain, hash)) { if (!pwallet->AbandonTransaction(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
} }
@ -2210,7 +2209,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
} }
if (pwallet->IsSpent(*locked_chain, outpt.hash, outpt.n)) { if (pwallet->IsSpent(outpt.hash, outpt.n)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
} }

View File

@ -281,13 +281,13 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
// Call GetImmatureCredit() once before adding the key to the wallet to // Call GetImmatureCredit() once before adding the key to the wallet to
// cache the current immature credit amount, which is 0. // cache the current immature credit amount, which is 0.
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 0); BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 0);
// Invalidate the cached vanue, add the key, and make sure a new immature // Invalidate the cached vanue, add the key, and make sure a new immature
// credit amount is calculated. // credit amount is calculated.
wtx.MarkDirty(); wtx.MarkDirty();
BOOST_CHECK(spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey())); BOOST_CHECK(spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()));
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 50*COIN); BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 50*COIN);
} }
static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime) static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)

View File

@ -452,7 +452,7 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
* Outpoint is spent if any non-conflicted transaction * Outpoint is spent if any non-conflicted transaction
* spends it: * spends it:
*/ */
bool CWallet::IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash, unsigned int n) const bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
{ {
const COutPoint outpoint(hash, n); const COutPoint outpoint(hash, n);
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range; std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
@ -463,7 +463,7 @@ bool CWallet::IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash
const uint256& wtxid = it->second; const uint256& wtxid = it->second;
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid); std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
if (mit != mapWallet.end()) { if (mit != mapWallet.end()) {
int depth = mit->second.GetDepthInMainChain(locked_chain); int depth = mit->second.GetDepthInMainChain();
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned())) if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
return true; // Spent return true; // Spent
} }
@ -913,7 +913,7 @@ bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
auto locked_chain = chain().lock(); auto locked_chain = chain().lock();
LOCK(cs_wallet); LOCK(cs_wallet);
const CWalletTx* wtx = GetWalletTx(hashTx); const CWalletTx* wtx = GetWalletTx(hashTx);
return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain(*locked_chain) == 0 && !wtx->InMempool(); return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
} }
void CWallet::MarkInputsDirty(const CTransactionRef& tx) void CWallet::MarkInputsDirty(const CTransactionRef& tx)
@ -926,9 +926,9 @@ void CWallet::MarkInputsDirty(const CTransactionRef& tx)
} }
} }
bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx) bool CWallet::AbandonTransaction(const uint256& hashTx)
{ {
auto locked_chain_recursive = chain().lock(); // Temporary. Removed in upcoming lock cleanup auto locked_chain = chain().lock(); // Temporary. Removed in upcoming lock cleanup
LOCK(cs_wallet); LOCK(cs_wallet);
WalletBatch batch(*database, "r+"); WalletBatch batch(*database, "r+");
@ -940,7 +940,7 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
auto it = mapWallet.find(hashTx); auto it = mapWallet.find(hashTx);
assert(it != mapWallet.end()); assert(it != mapWallet.end());
CWalletTx& origtx = it->second; CWalletTx& origtx = it->second;
if (origtx.GetDepthInMainChain(locked_chain) != 0 || origtx.InMempool()) { if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
return false; return false;
} }
@ -953,7 +953,7 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
auto it = mapWallet.find(now); auto it = mapWallet.find(now);
assert(it != mapWallet.end()); assert(it != mapWallet.end());
CWalletTx& wtx = it->second; CWalletTx& wtx = it->second;
int currentconfirm = wtx.GetDepthInMainChain(locked_chain); int currentconfirm = wtx.GetDepthInMainChain();
// If the orig tx was not in block, none of its spends can be // If the orig tx was not in block, none of its spends can be
assert(currentconfirm <= 0); assert(currentconfirm <= 0);
// if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon} // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
@ -1009,7 +1009,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
auto it = mapWallet.find(now); auto it = mapWallet.find(now);
assert(it != mapWallet.end()); assert(it != mapWallet.end());
CWalletTx& wtx = it->second; CWalletTx& wtx = it->second;
int currentconfirm = wtx.GetDepthInMainChain(*locked_chain); int currentconfirm = wtx.GetDepthInMainChain();
if (conflictconfirms < currentconfirm) { if (conflictconfirms < currentconfirm) {
// Block is 'more conflicted' than current confirm; update. // Block is 'more conflicted' than current confirm; update.
// Mark transaction as conflicted with this block. // Mark transaction as conflicted with this block.
@ -1691,7 +1691,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
return result; return result;
} }
void CWallet::ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain) void CWallet::ReacceptWalletTransactions()
{ {
// If transactions aren't being broadcasted, don't let them into local mempool either // If transactions aren't being broadcasted, don't let them into local mempool either
if (!fBroadcastTransactions) if (!fBroadcastTransactions)
@ -1704,7 +1704,7 @@ void CWallet::ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain)
CWalletTx& wtx = item.second; CWalletTx& wtx = item.second;
assert(wtx.GetHash() == wtxid); assert(wtx.GetHash() == wtxid);
int nDepth = wtx.GetDepthInMainChain(locked_chain); int nDepth = wtx.GetDepthInMainChain();
if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) { if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx)); mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
@ -1715,11 +1715,11 @@ void CWallet::ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain)
for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) { for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
CWalletTx& wtx = *(item.second); CWalletTx& wtx = *(item.second);
std::string unused_err_string; std::string unused_err_string;
wtx.SubmitMemoryPoolAndRelay(unused_err_string, false, locked_chain); wtx.SubmitMemoryPoolAndRelay(unused_err_string, false);
} }
} }
bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay, interfaces::Chain::Lock& locked_chain) bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay)
{ {
// Can't relay if wallet is not broadcasting // Can't relay if wallet is not broadcasting
if (!pwallet->GetBroadcastTransactions()) return false; if (!pwallet->GetBroadcastTransactions()) return false;
@ -1729,7 +1729,7 @@ bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay, in
// cause log spam. // cause log spam.
if (IsCoinBase()) return false; if (IsCoinBase()) return false;
// Don't try to submit conflicted or confirmed transactions. // Don't try to submit conflicted or confirmed transactions.
if (GetDepthInMainChain(locked_chain) != 0) return false; if (GetDepthInMainChain() != 0) return false;
// Submit transaction to mempool for relay // Submit transaction to mempool for relay
pwallet->WalletLogPrintf("Submitting wtx %s to mempool for relay\n", GetHash().ToString()); pwallet->WalletLogPrintf("Submitting wtx %s to mempool for relay\n", GetHash().ToString());
@ -1783,10 +1783,10 @@ CAmount CWalletTx::GetDebit(const isminefilter& filter) const
return debit; return debit;
} }
CAmount CWalletTx::GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const CAmount CWalletTx::GetCredit(const isminefilter& filter) const
{ {
// Must wait until coinbase is safely deep enough in the chain before valuing it // Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsImmatureCoinBase(locked_chain)) if (IsImmatureCoinBase())
return 0; return 0;
CAmount credit = 0; CAmount credit = 0;
@ -1800,16 +1800,16 @@ CAmount CWalletTx::GetCredit(interfaces::Chain::Lock& locked_chain, const ismine
return credit; return credit;
} }
CAmount CWalletTx::GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache) const CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
{ {
if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) { if (IsImmatureCoinBase() && IsInMainChain()) {
return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache); return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
} }
return 0; return 0;
} }
CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache, const isminefilter& filter) const CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter) const
{ {
if (pwallet == nullptr) if (pwallet == nullptr)
return 0; return 0;
@ -1818,7 +1818,7 @@ CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, boo
bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL; bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL;
// Must wait until coinbase is safely deep enough in the chain before valuing it // Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsImmatureCoinBase(locked_chain)) if (IsImmatureCoinBase())
return 0; return 0;
if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) { if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
@ -1830,7 +1830,7 @@ CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, boo
uint256 hashTx = GetHash(); uint256 hashTx = GetHash();
for (unsigned int i = 0; i < tx->vout.size(); i++) for (unsigned int i = 0; i < tx->vout.size(); i++)
{ {
if (!pwallet->IsSpent(locked_chain, hashTx, i) && (allow_used_addresses || !pwallet->IsUsedDestination(hashTx, i))) { if (!pwallet->IsSpent(hashTx, i) && (allow_used_addresses || !pwallet->IsUsedDestination(hashTx, i))) {
const CTxOut &txout = tx->vout[i]; const CTxOut &txout = tx->vout[i];
nCredit += pwallet->GetCredit(txout, filter); nCredit += pwallet->GetCredit(txout, filter);
if (!MoneyRange(nCredit)) if (!MoneyRange(nCredit))
@ -1845,9 +1845,9 @@ CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, boo
return nCredit; return nCredit;
} }
CAmount CWalletTx::GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache) const CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const
{ {
if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) { if (IsImmatureCoinBase() && IsInMainChain()) {
return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache); return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
} }
@ -1878,7 +1878,7 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set<uint25
{ {
// Quick answer in most cases // Quick answer in most cases
if (!locked_chain.checkFinalTx(*tx)) return false; if (!locked_chain.checkFinalTx(*tx)) return false;
int nDepth = GetDepthInMainChain(locked_chain); int nDepth = GetDepthInMainChain();
if (nDepth >= 1) return true; if (nDepth >= 1) return true;
if (nDepth < 0) return false; if (nDepth < 0) return false;
// using wtx's cached debit // using wtx's cached debit
@ -1954,7 +1954,7 @@ void CWallet::ResendWalletTransactions()
// any confirmed or conflicting txs. // any confirmed or conflicting txs.
if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue; if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
std::string unused_err_string; std::string unused_err_string;
if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true, *locked_chain)) ++submitted_tx_count; if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true)) ++submitted_tx_count;
} }
} // locked_chain and cs_wallet } // locked_chain and cs_wallet
@ -1991,9 +1991,9 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
{ {
const CWalletTx& wtx = entry.second; const CWalletTx& wtx = entry.second;
const bool is_trusted{wtx.IsTrusted(*locked_chain, trusted_parents)}; const bool is_trusted{wtx.IsTrusted(*locked_chain, trusted_parents)};
const int tx_depth{wtx.GetDepthInMainChain(*locked_chain)}; const int tx_depth{wtx.GetDepthInMainChain()};
const CAmount tx_credit_mine{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)}; const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)}; const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)};
if (is_trusted && tx_depth >= min_depth) { if (is_trusted && tx_depth >= min_depth) {
ret.m_mine_trusted += tx_credit_mine; ret.m_mine_trusted += tx_credit_mine;
ret.m_watchonly_trusted += tx_credit_watchonly; ret.m_watchonly_trusted += tx_credit_watchonly;
@ -2002,8 +2002,8 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
ret.m_mine_untrusted_pending += tx_credit_mine; ret.m_mine_untrusted_pending += tx_credit_mine;
ret.m_watchonly_untrusted_pending += tx_credit_watchonly; ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
} }
ret.m_mine_immature += wtx.GetImmatureCredit(*locked_chain); ret.m_mine_immature += wtx.GetImmatureCredit();
ret.m_watchonly_immature += wtx.GetImmatureWatchOnlyCredit(*locked_chain); ret.m_watchonly_immature += wtx.GetImmatureWatchOnlyCredit();
} }
} }
return ret; return ret;
@ -2047,10 +2047,10 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
continue; continue;
} }
if (wtx.IsImmatureCoinBase(locked_chain)) if (wtx.IsImmatureCoinBase())
continue; continue;
int nDepth = wtx.GetDepthInMainChain(locked_chain); int nDepth = wtx.GetDepthInMainChain();
if (nDepth < 0) if (nDepth < 0)
continue; continue;
@ -2110,7 +2110,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
if (IsLockedCoin(entry.first, i)) if (IsLockedCoin(entry.first, i))
continue; continue;
if (IsSpent(locked_chain, wtxid, i)) if (IsSpent(wtxid, i))
continue; continue;
isminetype mine = IsMine(wtx.tx->vout[i]); isminetype mine = IsMine(wtx.tx->vout[i]);
@ -2169,7 +2169,7 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Ch
for (const COutPoint& output : lockedCoins) { for (const COutPoint& output : lockedCoins) {
auto it = mapWallet.find(output.hash); auto it = mapWallet.find(output.hash);
if (it != mapWallet.end()) { if (it != mapWallet.end()) {
int depth = it->second.GetDepthInMainChain(locked_chain); int depth = it->second.GetDepthInMainChain();
if (depth >= 0 && output.n < it->second.tx->vout.size() && if (depth >= 0 && output.n < it->second.tx->vout.size() &&
IsMine(it->second.tx->vout[output.n]) == ISMINE_SPENDABLE) { IsMine(it->second.tx->vout[output.n]) == ISMINE_SPENDABLE) {
CTxDestination address; CTxDestination address;
@ -2909,7 +2909,7 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
} }
std::string err_string; std::string err_string;
if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) { if (!wtx.SubmitMemoryPoolAndRelay(err_string, true)) {
WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string); WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
} }
@ -3129,10 +3129,10 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain:
if (!wtx.IsTrusted(locked_chain, trusted_parents)) if (!wtx.IsTrusted(locked_chain, trusted_parents))
continue; continue;
if (wtx.IsImmatureCoinBase(locked_chain)) if (wtx.IsImmatureCoinBase())
continue; continue;
int nDepth = wtx.GetDepthInMainChain(locked_chain); int nDepth = wtx.GetDepthInMainChain();
if (nDepth < (wtx.IsFromMe(ISMINE_ALL) ? 0 : 1)) if (nDepth < (wtx.IsFromMe(ISMINE_ALL) ? 0 : 1))
continue; continue;
@ -3144,7 +3144,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain:
if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr)) if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr))
continue; continue;
CAmount n = IsSpent(locked_chain, walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue; CAmount n = IsSpent(walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue;
if (!balances.count(addr)) if (!balances.count(addr))
balances[addr] = 0; balances[addr] = 0;
@ -3908,7 +3908,7 @@ void CWallet::postInitProcess()
// Add wallet transactions that aren't already in a block to mempool // Add wallet transactions that aren't already in a block to mempool
// Do this here as mempool requires genesis block to be loaded // Do this here as mempool requires genesis block to be loaded
ReacceptWalletTransactions(*locked_chain); ReacceptWalletTransactions();
// Update wallet transactions with current mempool transactions. // Update wallet transactions with current mempool transactions.
chain().requestMempoolTransactions(*this); chain().requestMempoolTransactions(*this);
@ -3934,7 +3934,7 @@ CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
m_pre_split = false; m_pre_split = false;
} }
int CWalletTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const int CWalletTx::GetDepthInMainChain() const
{ {
assert(pwallet != nullptr); assert(pwallet != nullptr);
AssertLockHeld(pwallet->cs_wallet); AssertLockHeld(pwallet->cs_wallet);
@ -3943,19 +3943,19 @@ int CWalletTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const
return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1); return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1);
} }
int CWalletTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const int CWalletTx::GetBlocksToMaturity() const
{ {
if (!IsCoinBase()) if (!IsCoinBase())
return 0; return 0;
int chain_depth = GetDepthInMainChain(locked_chain); int chain_depth = GetDepthInMainChain();
assert(chain_depth >= 0); // coinbase tx should not be conflicted assert(chain_depth >= 0); // coinbase tx should not be conflicted
return std::max(0, (COINBASE_MATURITY+1) - chain_depth); return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
} }
bool CWalletTx::IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const bool CWalletTx::IsImmatureCoinBase() const
{ {
// note GetBlocksToMaturity is 0 for non-coinbase tx // note GetBlocksToMaturity is 0 for non-coinbase tx
return GetBlocksToMaturity(locked_chain) > 0; return GetBlocksToMaturity() > 0;
} }
std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const { std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const {

View File

@ -449,14 +449,14 @@ public:
//! filter decides which addresses will count towards the debit //! filter decides which addresses will count towards the debit
CAmount GetDebit(const isminefilter& filter) const; CAmount GetDebit(const isminefilter& filter) const;
CAmount GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const; CAmount GetCredit(const isminefilter& filter) const;
CAmount GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true) const; CAmount GetImmatureCredit(bool fUseCache = true) const;
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The
// annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid // annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
// having to resolve the issue of member access into incomplete type CWallet. // having to resolve the issue of member access into incomplete type CWallet.
CAmount GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS; CAmount GetAvailableCredit(bool fUseCache = true, const isminefilter& filter = ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS;
CAmount GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache=true) const; CAmount GetImmatureWatchOnlyCredit(const bool fUseCache = true) const;
CAmount GetChange() const; CAmount GetChange() const;
// Get the marginal bytes if spending the specified output from this transaction // Get the marginal bytes if spending the specified output from this transaction
@ -483,7 +483,7 @@ public:
int64_t GetTxTime() const; int64_t GetTxTime() const;
// Pass this transaction to node for mempool insertion and relay to peers if flag set to true // Pass this transaction to node for mempool insertion and relay to peers if flag set to true
bool SubmitMemoryPoolAndRelay(std::string& err_string, bool relay, interfaces::Chain::Lock& locked_chain); bool SubmitMemoryPoolAndRelay(std::string& err_string, bool relay);
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
@ -505,15 +505,15 @@ public:
// resolve the issue of member access into incomplete type CWallet. Note // resolve the issue of member access into incomplete type CWallet. Note
// that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)" // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
// in place. // in place.
int GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const NO_THREAD_SAFETY_ANALYSIS; int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS;
bool IsInMainChain(interfaces::Chain::Lock& locked_chain) const { return GetDepthInMainChain(locked_chain) > 0; } bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
/** /**
* @return number of blocks to maturity for this transaction: * @return number of blocks to maturity for this transaction:
* 0 : is not a coinbase transaction, or is a mature coinbase transaction * 0 : is not a coinbase transaction, or is a mature coinbase transaction
* >0 : is a coinbase transaction which matures in this many blocks * >0 : is a coinbase transaction which matures in this many blocks
*/ */
int GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const; int GetBlocksToMaturity() const;
bool isAbandoned() const { return m_confirm.status == CWalletTx::ABANDONED; } bool isAbandoned() const { return m_confirm.status == CWalletTx::ABANDONED; }
void setAbandoned() void setAbandoned()
{ {
@ -530,7 +530,7 @@ public:
void setConfirmed() { m_confirm.status = CWalletTx::CONFIRMED; } void setConfirmed() { m_confirm.status = CWalletTx::CONFIRMED; }
const uint256& GetHash() const { return tx->GetHash(); } const uint256& GetHash() const { return tx->GetHash(); }
bool IsCoinBase() const { return tx->IsCoinBase(); } bool IsCoinBase() const { return tx->IsCoinBase(); }
bool IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const; bool IsImmatureCoinBase() const;
}; };
class COutput class COutput
@ -808,7 +808,7 @@ public:
bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<OutputGroup> groups, bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<OutputGroup> groups,
std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, bool& bnb_used) const; std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
bool IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
// Whether this or any UTXO with the same CTxDestination has been spent. // Whether this or any UTXO with the same CTxDestination has been spent.
bool IsUsedDestination(const CTxDestination& dst) const; bool IsUsedDestination(const CTxDestination& dst) const;
@ -891,7 +891,7 @@ public:
}; };
ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate); ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate);
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override; void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
void ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ResendWalletTransactions(); void ResendWalletTransactions();
struct Balance { struct Balance {
CAmount m_mine_trusted{0}; //!< Trusted, at depth=GetBalance.min_depth or more CAmount m_mine_trusted{0}; //!< Trusted, at depth=GetBalance.min_depth or more
@ -1070,7 +1070,7 @@ public:
bool TransactionCanBeAbandoned(const uint256& hashTx) const; bool TransactionCanBeAbandoned(const uint256& hashTx) const;
/* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */ /* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
bool AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx); bool AbandonTransaction(const uint256& hashTx);
/** Mark a transaction as replaced by another transaction (e.g., BIP 125). */ /** Mark a transaction as replaced by another transaction (e.g., BIP 125). */
bool MarkReplaced(const uint256& originalHash, const uint256& newHash); bool MarkReplaced(const uint256& originalHash, const uint256& newHash);