aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
authorAntoine Riard <ariard@student.42.fr>2019-12-18 17:46:53 -0500
committerAntoine Riard <ariard@student.42.fr>2020-04-30 14:41:24 -0400
commit6a72f26968cf931c985d8d4797b6264274cabd06 (patch)
tree43314c9f174a36168f9c8f6f9662fcb66bb5c892 /src/wallet/wallet.cpp
parent841178820d31e1c24a00cb2c8fc0b1fd2f126f56 (diff)
downloadbitcoin-6a72f26968cf931c985d8d4797b6264274cabd06.tar.xz
[wallet] Remove locked_chain from CWallet, its RPCs and tests
This change is intended to make the bitcoin node and its rpc, network and gui interfaces more responsive while the wallet is in use. Currently because the node's cs_main mutex is always locked before the wallet's cs_wallet mutex (to prevent deadlocks), cs_main currently stays locked while the wallet does relatively slow things like creating and listing transactions. This commit only remmove chain lock tacking in wallet code, and invert lock order from cs_main, cs_wallet to cs_wallet, cs_main. must happen at once to avoid any deadlock. Previous commit were only removing Chain::Lock methods to Chain interface and enforcing they take cs_main. Remove LockChain method from CWallet and Chain::Lock interface.
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp48
1 files changed, 14 insertions, 34 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 6e8f7e0e8f..a20ede59fd 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -974,7 +974,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
const CWalletTx* wtx = GetWalletTx(hashTx);
return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
@@ -992,7 +991,6 @@ void CWallet::MarkInputsDirty(const CTransactionRef& tx)
bool CWallet::AbandonTransaction(const uint256& hashTx)
{
- auto locked_chain = chain().lock(); // Temporary. Removed in upcoming lock cleanup
LOCK(cs_wallet);
WalletBatch batch(*database, "r+");
@@ -1047,7 +1045,6 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
@@ -1110,7 +1107,6 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmatio
}
void CWallet::transactionAddedToMempool(const CTransactionRef& ptx) {
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, /* block_height */ 0, {}, /* nIndex */ 0);
SyncTransaction(ptx, confirm);
@@ -1132,7 +1128,6 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef &ptx) {
void CWallet::blockConnected(const CBlock& block, int height)
{
const uint256& block_hash = block.GetHash();
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
m_last_block_processed_height = height;
@@ -1146,7 +1141,6 @@ void CWallet::blockConnected(const CBlock& block, int height)
void CWallet::blockDisconnected(const CBlock& block, int height)
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
// At block disconnection, this will change an abandoned transaction to
@@ -1685,7 +1679,6 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
uint256 next_block_hash;
bool reorg = false;
if (chain().findBlock(block_hash, FoundBlock().data(block)) && !block.IsNull()) {
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
if (reorg) {
@@ -1714,7 +1707,6 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
break;
}
{
- auto locked_chain = chain().lock();
if (!next_block || reorg) {
// break successfully when rescan has reached the tip, or
// previous block is no longer on the chain due to a reorg
@@ -2002,8 +1994,7 @@ void CWallet::ResendWalletTransactions()
int submitted_tx_count = 0;
- { // locked_chain and cs_wallet scope
- auto locked_chain = chain().lock();
+ { // cs_wallet scope
LOCK(cs_wallet);
// Relay transactions
@@ -2016,7 +2007,7 @@ void CWallet::ResendWalletTransactions()
std::string unused_err_string;
if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true)) ++submitted_tx_count;
}
- } // locked_chain and cs_wallet
+ } // cs_wallet
if (submitted_tx_count > 0) {
WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
@@ -2044,7 +2035,6 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
Balance ret;
isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
std::set<uint256> trusted_parents;
for (const auto& entry : mapWallet)
@@ -2071,7 +2061,6 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CAmount balance = 0;
@@ -2550,7 +2539,6 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
// Acquire the locks to prevent races to the new locked unspents between the
// CreateTransaction call and LockCoin calls (when lockUnspents is true).
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CTransactionRef tx_new;
@@ -2701,7 +2689,6 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
int nBytes;
{
std::set<CInputCoin> setCoins;
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
txNew.nLockTime = GetLocktimeForNewTransaction(chain(), GetLastBlockHash(), GetLastBlockHeight());
{
@@ -3019,7 +3006,6 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
CWalletTx wtxNew(this, std::move(tx));
@@ -3059,11 +3045,6 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
- // Even if we don't use this lock in this function, we want to preserve
- // lock order in LoadToWallet if query of chain state is needed to know
- // tx status. If lock can't be taken (e.g bitcoin-wallet), tx confirmation
- // status may be not reliable.
- auto locked_chain = LockChain();
LOCK(cs_wallet);
fFirstRunRet = false;
@@ -3282,7 +3263,7 @@ void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations
}
}
-std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain::Lock& locked_chain) const
+std::map<CTxDestination, CAmount> CWallet::GetAddressBalances() const
{
std::map<CTxDestination, CAmount> balances;
@@ -3509,7 +3490,7 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
/** @} */ // end of Actions
-void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t>& mapKeyBirth) const {
+void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
AssertLockHeld(cs_wallet);
mapKeyBirth.clear();
@@ -3719,11 +3700,6 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b
// Recover readable keypairs:
CWallet dummyWallet(&chain, WalletLocation(), WalletDatabase::CreateDummy());
std::string backup_filename;
- // Even if we don't use this lock in this function, we want to preserve
- // lock order in LoadToWallet if query of chain state is needed to know
- // tx status. If lock can't be taken, tx confirmation status may be not
- // reliable.
- auto locked_chain = dummyWallet.LockChain();
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
return false;
}
@@ -3812,7 +3788,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
}
}
- auto locked_chain = chain.lock();
walletInstance->chainStateFlushed(chain.getTipLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
@@ -3926,9 +3901,18 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
- auto locked_chain = chain.lock();
LOCK(walletInstance->cs_wallet);
+ // Register wallet with validationinterface. It's done before rescan to avoid
+ // missing block connections between end of rescan and validation subscribing.
+ // Because of wallet lock being hold, block connection notifications are going to
+ // be pending on the validation-side until lock release. It's likely to have
+ // block processing duplicata (if rescan block range overlaps with notification one)
+ // but we guarantee at least than wallet state is correct after notifications delivery.
+ // This is temporary until rescan and notifications delivery are unified under same
+ // interface.
+ walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
+
int rescan_height = 0;
if (!gArgs.GetBoolArg("-rescan", false))
{
@@ -4029,9 +4013,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
}
}
- // Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain.
- walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
-
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
{
@@ -4091,7 +4072,6 @@ bool CWallet::UpgradeWallet(int version, std::string& error, std::vector<std::st
void CWallet::postInitProcess()
{
- auto locked_chain = chain().lock();
LOCK(cs_wallet);
// Add wallet transactions that aren't already in a block to mempool