Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) V0.12.0.x Locks fixes #491

Merged
merged 2 commits into from
Aug 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions src/darksend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,13 @@ bool CDarksendPool::SetCollateralAddress(std::string strAddress){
// Unlock coins after Darksend fails or succeeds
//
void CDarksendPool::UnlockCoins(){
LOCK(pwalletMain->cs_wallet);
BOOST_FOREACH(CTxIn v, lockedCoins)
pwalletMain->UnlockCoin(v.prevout);
while(true) {
TRY_LOCK(pwalletMain->cs_wallet, lockWallet);
if(!lockWallet) {MilliSleep(10); continue;}
BOOST_FOREACH(CTxIn v, lockedCoins)
pwalletMain->UnlockCoin(v.prevout);
break;
}

lockedCoins.clear();
}
Expand Down Expand Up @@ -1155,14 +1159,16 @@ void CDarksendPool::SendDarksendDenominate(std::vector<CTxIn>& vin, std::vector<

LogPrintf("Submitting tx %s\n", tx.ToString());

{
LOCK(cs_main);
while(true){
TRY_LOCK(cs_main, lockMain);
if(!lockMain) { MilliSleep(10); continue;}
if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL, false, true)){
LogPrintf("dsi -- transaction not valid! %s \n", tx.ToString());
UnlockCoins();
SetNull();
return;
}
break;
}
}

Expand Down Expand Up @@ -1352,25 +1358,24 @@ void CDarksendPool::ClearLastMessage()
//
bool CDarksendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
{
if(!fEnableDarksend) return false;
if(fMasterNode) return false;
if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) return false;
if(GetEntriesCount() > 0) {
strAutoDenomResult = _("Mixing in progress...");
return false;
}

TRY_LOCK(cs_darksend, lockDS);
if(!lockDS) {
strAutoDenomResult = _("Lock is already in place.");
return false;
}

LOCK(cs_darksend);

if(!masternodeSync.IsBlockchainSynced()) {
strAutoDenomResult = _("Can't mix while sync in progress.");
return false;
}
if(!fEnableDarksend) return false;
if(fMasterNode) return false;
if(state == POOL_STATUS_ERROR || state == POOL_STATUS_SUCCESS) return false;
if(GetEntriesCount() > 0) {
strAutoDenomResult = _("Mixing in progress...");
return false;
}

if (!fDryRun && pwalletMain->IsLocked()){
strAutoDenomResult = _("Wallet is locked.");
Expand Down
23 changes: 12 additions & 11 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2616,8 +2616,10 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
boost::this_thread::interruption_point();

bool fInitialDownload;
{
LOCK(cs_main);
while(true) {
TRY_LOCK(cs_main, lockMain);
if(!lockMain) { MilliSleep(10); continue; }

pindexMostWork = FindMostWorkChain();

// Whether we have anything to do at all.
Expand All @@ -2629,6 +2631,7 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) {

pindexNewTip = chainActive.Tip();
fInitialDownload = IsInitialBlockDownload();
break;
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).

Expand Down Expand Up @@ -3261,8 +3264,10 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis
// Preliminary checks
bool checked = CheckBlock(*pblock, state);

{
LOCK(cs_main);
while(true) {
TRY_LOCK(cs_main, lockMain);
if(!lockMain) { MilliSleep(10); continue; }

MarkBlockAsReceived(pblock->GetHash());
if (!checked) {
return error("%s : CheckBlock FAILED", __func__);
Expand All @@ -3277,6 +3282,7 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis
CheckBlockIndex();
if (!ret)
return error("%s : AcceptBlock FAILED", __func__);
break;
}

if (!ActivateBestChain(state, pblock))
Expand Down Expand Up @@ -4876,12 +4882,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CBlock block;
vRecv >> block;

TRY_LOCK(cs_main, lockMainBlock);
if(!lockMainBlock && masternodeSync.IsBlockchainSynced()) {
LogPrintf("block -- failed to lock cs_main - %s\n", block.GetHash().ToString());
return false;
}

CInv inv(MSG_BLOCK, block.GetHash());
LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom->id);

Expand All @@ -4894,7 +4894,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0) {
Misbehaving(pfrom->GetId(), nDoS);
TRY_LOCK(cs_main, lockMain);
if(lockMain) Misbehaving(pfrom->GetId(), nDoS);
}
}

Expand Down
34 changes: 24 additions & 10 deletions src/qt/overviewpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,10 @@ void OverviewPage::updateDarksendProgress()

if(!pwalletMain) return;

int64_t nBalance = pwalletMain->GetBalance();
QString strAmountAndRounds;
QString strAnonymizeDarkcoinAmount = BitcoinUnits::formatHtmlWithUnit(nDisplayUnit, nAnonymizeDarkcoinAmount * COIN, false, BitcoinUnits::separatorAlways);

if(nBalance == 0)
if(currentBalance == 0)
{
ui->darksendProgress->setValue(0);
ui->darksendProgress->setToolTip(tr("No inputs detected"));
Expand All @@ -336,9 +335,24 @@ void OverviewPage::updateDarksendProgress()
return;
}

int64_t nDenominatedUnconfirmedBalance = pwalletMain->GetDenominatedBalance(true);
int64_t nMaxToAnonymize = pwalletMain->GetAnonymizableBalance() +
pwalletMain->GetAnonymizedBalance() + nDenominatedUnconfirmedBalance;
CAmount nDenominatedConfirmedBalance;
CAmount nDenominatedUnconfirmedBalance;
CAmount nAnonymizableBalance;
CAmount nNormalizedAnonymizedBalance;
double nAverageAnonymizedRounds;

{
TRY_LOCK(cs_main, lockMain);
if(!lockMain) return;

nDenominatedConfirmedBalance = pwalletMain->GetDenominatedBalance();
nDenominatedUnconfirmedBalance = pwalletMain->GetDenominatedBalance(true);
nAnonymizableBalance = pwalletMain->GetAnonymizableBalance();
nNormalizedAnonymizedBalance = pwalletMain->GetNormalizedAnonymizedBalance();
nAverageAnonymizedRounds = pwalletMain->GetAverageAnonymizedRounds();
}

CAmount nMaxToAnonymize = nAnonymizableBalance + currentAnonymizedBalance + nDenominatedUnconfirmedBalance;

// If it's more than the anon threshold, limit to that.
if(nMaxToAnonymize > nAnonymizeDarkcoinAmount*COIN) nMaxToAnonymize = nAnonymizeDarkcoinAmount*COIN;
Expand Down Expand Up @@ -371,16 +385,16 @@ void OverviewPage::updateDarksendProgress()
// completeness of full amount anonimization
float anonFullPart = 0;

int64_t denominatedBalance = pwalletMain->GetDenominatedBalance() + nDenominatedUnconfirmedBalance;
CAmount denominatedBalance = nDenominatedConfirmedBalance + nDenominatedUnconfirmedBalance;
denomPart = (float)denominatedBalance / nMaxToAnonymize;
denomPart = denomPart > 1 ? 1 : denomPart;
denomPart *= 100;

anonNormPart = (float)pwalletMain->GetNormalizedAnonymizedBalance() / nMaxToAnonymize;
anonNormPart = (float)nNormalizedAnonymizedBalance / nMaxToAnonymize;
anonNormPart = anonNormPart > 1 ? 1 : anonNormPart;
anonNormPart *= 100;

anonFullPart = (float)pwalletMain->GetAnonymizedBalance() / nMaxToAnonymize;
anonFullPart = (float)currentAnonymizedBalance / nMaxToAnonymize;
anonFullPart = anonFullPart > 1 ? 1 : anonFullPart;
anonFullPart *= 100;

Expand All @@ -404,7 +418,7 @@ void OverviewPage::updateDarksendProgress()
tr("Anonymized") + ": %4%<br/>" +
tr("Denominated inputs have %5 of %n rounds on average", "", nDarksendRounds))
.arg(progress).arg(denomPart).arg(anonNormPart).arg(anonFullPart)
.arg(pwalletMain->GetAverageAnonymizedRounds());
.arg(nAverageAnonymizedRounds);
ui->darksendProgress->setToolTip(strToolPip);
}

Expand Down Expand Up @@ -486,7 +500,7 @@ void OverviewPage::toggleDarksend(){
settings.setValue("hasMixed", "hasMixed");
}
if(!fEnableDarksend){
int64_t balance = pwalletMain->GetBalance();
int64_t balance = currentBalance;
float minAmount = 1.49 * COIN;
if(balance < minAmount){
QString strMinAmount(BitcoinUnits::formatWithUnit(nDisplayUnit, minAmount));
Expand Down
3 changes: 3 additions & 0 deletions src/qt/sendcoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,9 @@ void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfir

void SendCoinsDialog::updateDisplayUnit()
{
TRY_LOCK(cs_main, lockMain);
if(!lockMain) return;

setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getAnonymizedBalance(),
model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance());
CoinControlDialog::coinControl->useDarkSend = ui->checkUseDarksend->isChecked();
Expand Down
3 changes: 3 additions & 0 deletions src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ void WalletModel::pollBalanceChanged()

void WalletModel::checkBalanceChanged()
{
TRY_LOCK(cs_main, lockMain);
if(!lockMain) return;

CAmount newBalance = getBalance();
CAmount newUnconfirmedBalance = getUnconfirmedBalance();
CAmount newImmatureBalance = getImmatureBalance();
Expand Down
18 changes: 12 additions & 6 deletions src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2434,9 +2434,11 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)

LogPrintf("PrepareDarksendDenominate - preparing darksend denominate . Got: %d \n", nValueIn);

LOCK(cs_wallet);
BOOST_FOREACH(CTxIn v, vCoins)
LockCoin(v.prevout);
{
LOCK(cs_wallet);
BOOST_FOREACH(CTxIn v, vCoins)
LockCoin(v.prevout);
}

int64_t nValueLeft = nValueIn;
std::vector<CTxOut> vOut;
Expand Down Expand Up @@ -2503,12 +2505,16 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
if(nValueLeft == 0) break;
}

// unlock unused coins
BOOST_FOREACH(CTxIn v, vCoins)
UnlockCoin(v.prevout);
{
// unlock unused coins
LOCK(cs_wallet);
BOOST_FOREACH(CTxIn v, vCoins)
UnlockCoin(v.prevout);
}

if(darkSendPool.GetDenominations(vOut) != darkSendPool.sessionDenom) {
// unlock used coins on failure
LOCK(cs_wallet);
BOOST_FOREACH(CTxIn v, vCoinsResult)
UnlockCoin(v.prevout);
return "Error: can't make current denominated outputs";
Expand Down