Merge pull request #4058
55a1db4
Solve chainActive-related locking issues (Wladimir J. van der Laan)e07c943
Add AssertLockHeld for cs_main to ChainActive-using functions (Wladimir J. van der Laan)
This commit is contained in:
commit
2bbecc84e2
24
src/main.cpp
24
src/main.cpp
|
@ -474,6 +474,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
|
||||||
|
|
||||||
bool IsStandardTx(const CTransaction& tx, string& reason)
|
bool IsStandardTx(const CTransaction& tx, string& reason)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
|
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
|
||||||
reason = "version";
|
reason = "version";
|
||||||
return false;
|
return false;
|
||||||
|
@ -556,6 +557,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
|
||||||
|
|
||||||
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
|
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// Time based nLockTime implemented in 0.1.6
|
// Time based nLockTime implemented in 0.1.6
|
||||||
if (tx.nLockTime == 0)
|
if (tx.nLockTime == 0)
|
||||||
return true;
|
return true;
|
||||||
|
@ -667,6 +669,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& inputs)
|
||||||
|
|
||||||
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
CBlock blockTmp;
|
CBlock blockTmp;
|
||||||
|
|
||||||
if (pblock == NULL) {
|
if (pblock == NULL) {
|
||||||
|
@ -813,6 +816,7 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree,
|
||||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||||
bool* pfMissingInputs, bool fRejectInsaneFee)
|
bool* pfMissingInputs, bool fRejectInsaneFee)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
*pfMissingInputs = false;
|
*pfMissingInputs = false;
|
||||||
|
|
||||||
|
@ -958,6 +962,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
|
||||||
{
|
{
|
||||||
if (hashBlock == 0 || nIndex == -1)
|
if (hashBlock == 0 || nIndex == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
// Find the block it claims to be in
|
// Find the block it claims to be in
|
||||||
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
|
||||||
|
@ -981,6 +986,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
|
||||||
|
|
||||||
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
|
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
int nResult = GetDepthInMainChainINTERNAL(pindexRet);
|
int nResult = GetDepthInMainChainINTERNAL(pindexRet);
|
||||||
if (nResult == 0 && !mempool.exists(GetHash()))
|
if (nResult == 0 && !mempool.exists(GetHash()))
|
||||||
return -1; // Not in chain, not in mempool
|
return -1; // Not in chain, not in mempool
|
||||||
|
@ -1304,6 +1310,7 @@ int GetNumBlocksOfPeers()
|
||||||
|
|
||||||
bool IsInitialBlockDownload()
|
bool IsInitialBlockDownload()
|
||||||
{
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
|
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
|
||||||
return true;
|
return true;
|
||||||
static int64_t nLastUpdate;
|
static int64_t nLastUpdate;
|
||||||
|
@ -1323,6 +1330,7 @@ CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
|
||||||
|
|
||||||
void CheckForkWarningConditions()
|
void CheckForkWarningConditions()
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// Before we get past initial download, we cannot reliably alert about forks
|
// Before we get past initial download, we cannot reliably alert about forks
|
||||||
// (we assume we don't get stuck on a fork before the last checkpoint)
|
// (we assume we don't get stuck on a fork before the last checkpoint)
|
||||||
if (IsInitialBlockDownload())
|
if (IsInitialBlockDownload())
|
||||||
|
@ -1368,6 +1376,7 @@ void CheckForkWarningConditions()
|
||||||
|
|
||||||
void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// If we are on a fork that is sufficiently large, set a warning flag
|
// If we are on a fork that is sufficiently large, set a warning flag
|
||||||
CBlockIndex* pfork = pindexNewForkTip;
|
CBlockIndex* pfork = pindexNewForkTip;
|
||||||
CBlockIndex* plonger = chainActive.Tip();
|
CBlockIndex* plonger = chainActive.Tip();
|
||||||
|
@ -2078,6 +2087,7 @@ void static FindMostWorkChain() {
|
||||||
|
|
||||||
// Try to activate to the most-work chain (thereby connecting it).
|
// Try to activate to the most-work chain (thereby connecting it).
|
||||||
bool ActivateBestChain(CValidationState &state) {
|
bool ActivateBestChain(CValidationState &state) {
|
||||||
|
LOCK(cs_main);
|
||||||
CBlockIndex *pindexOldTip = chainActive.Tip();
|
CBlockIndex *pindexOldTip = chainActive.Tip();
|
||||||
bool fComplete = false;
|
bool fComplete = false;
|
||||||
while (!fComplete) {
|
while (!fComplete) {
|
||||||
|
@ -2162,6 +2172,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
|
||||||
if (!ActivateBestChain(state))
|
if (!ActivateBestChain(state))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
if (pindexNew == chainActive.Tip())
|
if (pindexNew == chainActive.Tip())
|
||||||
{
|
{
|
||||||
// Clear fork warning if its no longer applicable
|
// Clear fork warning if its no longer applicable
|
||||||
|
@ -2344,6 +2355,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
|
||||||
|
|
||||||
bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
|
bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
uint256 hash = block.GetHash();
|
uint256 hash = block.GetHash();
|
||||||
if (mapBlockIndex.count(hash))
|
if (mapBlockIndex.count(hash))
|
||||||
|
@ -2455,6 +2467,7 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
|
||||||
|
|
||||||
int64_t CBlockIndex::GetMedianTime() const
|
int64_t CBlockIndex::GetMedianTime() const
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
const CBlockIndex* pindex = this;
|
const CBlockIndex* pindex = this;
|
||||||
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
||||||
{
|
{
|
||||||
|
@ -2467,6 +2480,7 @@ int64_t CBlockIndex::GetMedianTime() const
|
||||||
|
|
||||||
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
|
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// Filter out duplicate requests
|
// Filter out duplicate requests
|
||||||
if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd)
|
if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd)
|
||||||
return;
|
return;
|
||||||
|
@ -2948,6 +2962,7 @@ bool LoadBlockIndex()
|
||||||
|
|
||||||
|
|
||||||
bool InitBlockIndex() {
|
bool InitBlockIndex() {
|
||||||
|
LOCK(cs_main);
|
||||||
// Check whether we're already initialized
|
// Check whether we're already initialized
|
||||||
if (chainActive.Genesis() != NULL)
|
if (chainActive.Genesis() != NULL)
|
||||||
return true;
|
return true;
|
||||||
|
@ -2983,6 +2998,7 @@ bool InitBlockIndex() {
|
||||||
|
|
||||||
void PrintBlockTree()
|
void PrintBlockTree()
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// pre-compute tree structure
|
// pre-compute tree structure
|
||||||
map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
|
map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
|
||||||
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
|
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
|
||||||
|
@ -4186,6 +4202,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
|
||||||
|
if (!lockMain)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Address refresh broadcast
|
// Address refresh broadcast
|
||||||
static int64_t nLastRebroadcast;
|
static int64_t nLastRebroadcast;
|
||||||
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
|
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
|
||||||
|
@ -4236,10 +4256,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||||
pto->PushMessage("addr", vAddr);
|
pto->PushMessage("addr", vAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY_LOCK(cs_main, lockMain);
|
|
||||||
if (!lockMain)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
CNodeState &state = *State(pto->GetId());
|
CNodeState &state = *State(pto->GetId());
|
||||||
if (state.fShouldBan) {
|
if (state.fShouldBan) {
|
||||||
if (pto->addr.IsLocal())
|
if (pto->addr.IsLocal())
|
||||||
|
|
|
@ -55,6 +55,7 @@ int ClientModel::getNumConnections(unsigned int flags) const
|
||||||
|
|
||||||
int ClientModel::getNumBlocks() const
|
int ClientModel::getNumBlocks() const
|
||||||
{
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
return chainActive.Height();
|
return chainActive.Height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ quint64 ClientModel::getTotalBytesSent() const
|
||||||
|
|
||||||
QDateTime ClientModel::getLastBlockDate() const
|
QDateTime ClientModel::getLastBlockDate() const
|
||||||
{
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
if (chainActive.Tip())
|
if (chainActive.Tip())
|
||||||
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
|
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
|
||||||
else
|
else
|
||||||
|
@ -84,6 +86,7 @@ QDateTime ClientModel::getLastBlockDate() const
|
||||||
|
|
||||||
double ClientModel::getVerificationProgress() const
|
double ClientModel::getVerificationProgress() const
|
||||||
{
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
return Checkpoints::GuessVerificationProgress(chainActive.Tip());
|
return Checkpoints::GuessVerificationProgress(chainActive.Tip());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
if (!IsFinalTx(wtx, chainActive.Height() + 1))
|
if (!IsFinalTx(wtx, chainActive.Height() + 1))
|
||||||
{
|
{
|
||||||
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
||||||
|
@ -45,8 +46,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u
|
||||||
{
|
{
|
||||||
QString strHTML;
|
QString strHTML;
|
||||||
|
|
||||||
{
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
strHTML.reserve(4000);
|
strHTML.reserve(4000);
|
||||||
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
|
strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
|
||||||
|
|
||||||
|
@ -271,8 +271,6 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u
|
||||||
strHTML += "<br><b>" + tr("Inputs") + ":</b>";
|
strHTML += "<br><b>" + tr("Inputs") + ":</b>";
|
||||||
strHTML += "<ul>";
|
strHTML += "<ul>";
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||||
{
|
{
|
||||||
COutPoint prevout = txin.prevout;
|
COutPoint prevout = txin.prevout;
|
||||||
|
@ -296,12 +294,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
strHTML += "</ul>";
|
strHTML += "</ul>";
|
||||||
}
|
}
|
||||||
|
|
||||||
strHTML += "</font></html>";
|
strHTML += "</font></html>";
|
||||||
}
|
|
||||||
return strHTML;
|
return strHTML;
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||||
|
|
||||||
void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
// Determine transaction status
|
// Determine transaction status
|
||||||
|
|
||||||
// Find the block the tx is in
|
// Find the block the tx is in
|
||||||
|
@ -234,6 +235,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||||
|
|
||||||
bool TransactionRecord::statusUpdateNeeded()
|
bool TransactionRecord::statusUpdateNeeded()
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
return status.cur_num_blocks != chainActive.Height();
|
return status.cur_num_blocks != chainActive.Height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ public:
|
||||||
qDebug() << "TransactionTablePriv::refreshWallet";
|
qDebug() << "TransactionTablePriv::refreshWallet";
|
||||||
cachedWallet.clear();
|
cachedWallet.clear();
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
|
for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
if(TransactionRecord::showTransaction(it->second))
|
if(TransactionRecord::showTransaction(it->second))
|
||||||
|
@ -96,7 +96,7 @@ public:
|
||||||
{
|
{
|
||||||
qDebug() << "TransactionTablePriv::updateWallet : " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
|
qDebug() << "TransactionTablePriv::updateWallet : " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
|
|
||||||
// Find transaction in wallet
|
// Find transaction in wallet
|
||||||
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
|
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
|
||||||
|
@ -190,10 +190,9 @@ public:
|
||||||
// If a status update is needed (blocks came in since last check),
|
// If a status update is needed (blocks came in since last check),
|
||||||
// update the status of this transaction from the wallet. Otherwise,
|
// update the status of this transaction from the wallet. Otherwise,
|
||||||
// simply re-use the cached status.
|
// simply re-use the cached status.
|
||||||
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
if(rec->statusUpdateNeeded())
|
if(rec->statusUpdateNeeded())
|
||||||
{
|
{
|
||||||
{
|
|
||||||
LOCK(wallet->cs_wallet);
|
|
||||||
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
|
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
|
||||||
|
|
||||||
if(mi != wallet->mapWallet.end())
|
if(mi != wallet->mapWallet.end())
|
||||||
|
@ -201,7 +200,6 @@ public:
|
||||||
rec->updateStatus(mi->second);
|
rec->updateStatus(mi->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -213,7 +211,7 @@ public:
|
||||||
QString describe(TransactionRecord *rec, int unit)
|
QString describe(TransactionRecord *rec, int unit)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
|
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
|
||||||
if(mi != wallet->mapWallet.end())
|
if(mi != wallet->mapWallet.end())
|
||||||
{
|
{
|
||||||
|
@ -228,17 +226,12 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren
|
||||||
QAbstractTableModel(parent),
|
QAbstractTableModel(parent),
|
||||||
wallet(wallet),
|
wallet(wallet),
|
||||||
walletModel(parent),
|
walletModel(parent),
|
||||||
priv(new TransactionTablePriv(wallet, this)),
|
priv(new TransactionTablePriv(wallet, this))
|
||||||
cachedNumBlocks(0)
|
|
||||||
{
|
{
|
||||||
columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount");
|
columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount");
|
||||||
|
|
||||||
priv->refreshWallet();
|
priv->refreshWallet();
|
||||||
|
|
||||||
QTimer *timer = new QTimer(this);
|
|
||||||
connect(timer, SIGNAL(timeout()), this, SLOT(updateConfirmations()));
|
|
||||||
timer->start(MODEL_UPDATE_DELAY);
|
|
||||||
|
|
||||||
connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,16 +250,12 @@ void TransactionTableModel::updateTransaction(const QString &hash, int status)
|
||||||
|
|
||||||
void TransactionTableModel::updateConfirmations()
|
void TransactionTableModel::updateConfirmations()
|
||||||
{
|
{
|
||||||
if(chainActive.Height() != cachedNumBlocks)
|
|
||||||
{
|
|
||||||
cachedNumBlocks = chainActive.Height();
|
|
||||||
// Blocks came in since last poll.
|
// Blocks came in since last poll.
|
||||||
// Invalidate status (number of confirmations) and (possibly) description
|
// Invalidate status (number of confirmations) and (possibly) description
|
||||||
// for all rows. Qt is smart enough to only actually request the data for the
|
// for all rows. Qt is smart enough to only actually request the data for the
|
||||||
// visible rows.
|
// visible rows.
|
||||||
emit dataChanged(index(0, Status), index(priv->size()-1, Status));
|
emit dataChanged(index(0, Status), index(priv->size()-1, Status));
|
||||||
emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
|
emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TransactionTableModel::rowCount(const QModelIndex &parent) const
|
int TransactionTableModel::rowCount(const QModelIndex &parent) const
|
||||||
|
|
|
@ -69,7 +69,6 @@ private:
|
||||||
WalletModel *walletModel;
|
WalletModel *walletModel;
|
||||||
QStringList columns;
|
QStringList columns;
|
||||||
TransactionTablePriv *priv;
|
TransactionTablePriv *priv;
|
||||||
int cachedNumBlocks;
|
|
||||||
|
|
||||||
QString lookupAddress(const std::string &address, bool tooltip) const;
|
QString lookupAddress(const std::string &address, bool tooltip) const;
|
||||||
QVariant addressColor(const TransactionRecord *wtx) const;
|
QVariant addressColor(const TransactionRecord *wtx) const;
|
||||||
|
|
|
@ -98,11 +98,21 @@ void WalletModel::updateStatus()
|
||||||
|
|
||||||
void WalletModel::pollBalanceChanged()
|
void WalletModel::pollBalanceChanged()
|
||||||
{
|
{
|
||||||
|
bool heightChanged = false;
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
if(chainActive.Height() != cachedNumBlocks)
|
if(chainActive.Height() != cachedNumBlocks)
|
||||||
{
|
{
|
||||||
// Balance and number of transactions might have changed
|
// Balance and number of transactions might have changed
|
||||||
cachedNumBlocks = chainActive.Height();
|
cachedNumBlocks = chainActive.Height();
|
||||||
|
heightChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(heightChanged)
|
||||||
|
{
|
||||||
checkBalanceChanged();
|
checkBalanceChanged();
|
||||||
|
if(transactionTableModel)
|
||||||
|
transactionTableModel->updateConfirmations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +530,7 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||||
// returns a list of COutputs from COutPoints
|
// returns a list of COutputs from COutPoints
|
||||||
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
|
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
BOOST_FOREACH(const COutPoint& outpoint, vOutpoints)
|
BOOST_FOREACH(const COutPoint& outpoint, vOutpoints)
|
||||||
{
|
{
|
||||||
if (!wallet->mapWallet.count(outpoint.hash)) continue;
|
if (!wallet->mapWallet.count(outpoint.hash)) continue;
|
||||||
|
@ -533,7 +543,7 @@ void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vect
|
||||||
|
|
||||||
bool WalletModel::isSpent(const COutPoint& outpoint) const
|
bool WalletModel::isSpent(const COutPoint& outpoint) const
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
return wallet->IsSpent(outpoint.hash, outpoint.n);
|
return wallet->IsSpent(outpoint.hash, outpoint.n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +553,7 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
||||||
std::vector<COutput> vCoins;
|
std::vector<COutput> vCoins;
|
||||||
wallet->AvailableCoins(vCoins);
|
wallet->AvailableCoins(vCoins);
|
||||||
|
|
||||||
LOCK(wallet->cs_wallet); // ListLockedCoins, mapWallet
|
LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet
|
||||||
std::vector<COutPoint> vLockedCoins;
|
std::vector<COutPoint> vLockedCoins;
|
||||||
wallet->ListLockedCoins(vLockedCoins);
|
wallet->ListLockedCoins(vLockedCoins);
|
||||||
|
|
||||||
|
@ -575,25 +585,25 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
||||||
|
|
||||||
bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
|
bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
return wallet->IsLockedCoin(hash, n);
|
return wallet->IsLockedCoin(hash, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletModel::lockCoin(COutPoint& output)
|
void WalletModel::lockCoin(COutPoint& output)
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
wallet->LockCoin(output);
|
wallet->LockCoin(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletModel::unlockCoin(COutPoint& output)
|
void WalletModel::unlockCoin(COutPoint& output)
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
wallet->UnlockCoin(output);
|
wallet->UnlockCoin(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
|
void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
|
||||||
{
|
{
|
||||||
LOCK(wallet->cs_wallet);
|
LOCK2(cs_main, wallet->cs_wallet);
|
||||||
wallet->ListLockedCoins(vOutpts);
|
wallet->ListLockedCoins(vOutpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,7 +607,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
|
||||||
|
|
||||||
void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock)
|
void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock)
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true))
|
if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true))
|
||||||
return; // Not one of ours
|
return; // Not one of ours
|
||||||
|
|
||||||
|
@ -835,7 +835,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||||
|
|
||||||
CBlockIndex* pindex = pindexStart;
|
CBlockIndex* pindex = pindexStart;
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
|
|
||||||
// no need to read and scan block, if block was created before
|
// no need to read and scan block, if block was created before
|
||||||
// our wallet birthday (as adjusted for block time variability)
|
// our wallet birthday (as adjusted for block time variability)
|
||||||
|
@ -870,7 +870,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||||
|
|
||||||
void CWallet::ReacceptWalletTransactions()
|
void CWallet::ReacceptWalletTransactions()
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
|
||||||
{
|
{
|
||||||
const uint256& wtxid = item.first;
|
const uint256& wtxid = item.first;
|
||||||
|
@ -965,7 +965,7 @@ int64_t CWallet::GetBalance() const
|
||||||
{
|
{
|
||||||
int64_t nTotal = 0;
|
int64_t nTotal = 0;
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
const CWalletTx* pcoin = &(*it).second;
|
||||||
|
@ -981,7 +981,7 @@ int64_t CWallet::GetUnconfirmedBalance() const
|
||||||
{
|
{
|
||||||
int64_t nTotal = 0;
|
int64_t nTotal = 0;
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
const CWalletTx* pcoin = &(*it).second;
|
||||||
|
@ -996,7 +996,7 @@ int64_t CWallet::GetImmatureBalance() const
|
||||||
{
|
{
|
||||||
int64_t nTotal = 0;
|
int64_t nTotal = 0;
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
const CWalletTx* pcoin = &(*it).second;
|
||||||
|
|
Loading…
Reference in New Issue