Skip to content

Commit

Permalink
Fix potential deadlock in CInstantSend::UpdateLockedTransaction (#1571)
Browse files Browse the repository at this point in the history
* cs_wallet -> cs_instantsend:

getinfo(...) - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL)
  CAmount CWallet::GetBalance() const - LOCK2(cs_main, cs_wallet)
    CWalletTx::IsTrusted()
      GetDepthInMainChain()
        CInstantSend::IsLockedInstantSendTransaction(...) - LOCK(cs_instantsend)

cs_wallet -> cs_instantsend:

CWallet::ReacceptWalletTransactions() - LOCK2(cs_main, cs_wallet)
  GetDepthInMainChain()
    CInstantSend::IsLockedInstantSendTransaction(...) - LOCK(cs_instantsend)

cs_instantsend -> cs_wallet:

void CInstantSend::UpdateLockedTransaction(...) - LOCK(cs_instantsend)
  CWallet::UpdatedTransaction(...) - LOCK(cs_wallet)

* AssertLockHeld added
  • Loading branch information
Ilya Savinov authored and UdjinM6 committed Aug 11, 2017
1 parent 0fc1343 commit 4a9fbca
Showing 1 changed file with 33 additions and 5 deletions.
38 changes: 33 additions & 5 deletions src/instantx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,13 @@ void CInstantSend::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataSt
CTxLockVote vote;
vRecv >> vote;

LOCK2(cs_main, cs_instantsend);
LOCK(cs_main);
#ifdef ENABLE_WALLET
if (pwalletMain)
LOCK(pwalletMain->cs_wallet);
#endif
LOCK(cs_instantsend);


uint256 nVoteHash = vote.GetHash();

Expand Down Expand Up @@ -251,7 +257,13 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate)
//received a consensus vote
bool CInstantSend::ProcessTxLockVote(CNode* pfrom, CTxLockVote& vote)
{
LOCK2(cs_main, cs_instantsend);
// cs_main, cs_wallet and cs_instantsend should be already locked
AssertLockHeld(cs_main);
#ifdef ENABLE_WALLET
if (pwalletMain)
AssertLockHeld(pwalletMain->cs_wallet);
#endif
AssertLockHeld(cs_instantsend);

uint256 txHash = vote.GetTxHash();

Expand Down Expand Up @@ -362,7 +374,13 @@ bool CInstantSend::ProcessTxLockVote(CNode* pfrom, CTxLockVote& vote)

void CInstantSend::ProcessOrphanTxLockVotes()
{
LOCK2(cs_main, cs_instantsend);
LOCK(cs_main);
#ifdef ENABLE_WALLET
if (pwalletMain)
LOCK(pwalletMain->cs_wallet);
#endif
LOCK(cs_instantsend);

std::map<uint256, CTxLockVote>::iterator it = mapTxLockVotesOrphan.begin();
while(it != mapTxLockVotesOrphan.end()) {
if(ProcessTxLockVote(NULL, it->second)) {
Expand Down Expand Up @@ -406,7 +424,12 @@ bool CInstantSend::IsEnoughOrphanVotesForTxAndOutPoint(const uint256& txHash, co

void CInstantSend::TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCandidate)
{
LOCK2(cs_main, cs_instantsend);
LOCK(cs_main);
#ifdef ENABLE_WALLET
if (pwalletMain)
LOCK(pwalletMain->cs_wallet);
#endif
LOCK(cs_instantsend);

uint256 txHash = txLockCandidate.txLockRequest.GetHash();
if(txLockCandidate.IsAllOutPointsReady() && !IsLockedInstantSendTransaction(txHash)) {
Expand All @@ -421,7 +444,12 @@ void CInstantSend::TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCand

void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandidate)
{
LOCK(cs_instantsend);
// cs_wallet and cs_instantsend should be already locked
#ifdef ENABLE_WALLET
if (pwalletMain)
AssertLockHeld(pwalletMain->cs_wallet);
#endif
AssertLockHeld(cs_instantsend);

uint256 txHash = txLockCandidate.GetHash();

Expand Down

0 comments on commit 4a9fbca

Please sign in to comment.