Skip to content

Commit

Permalink
qt: Modernize 'confirmed' terminology in shown tx status
Browse files Browse the repository at this point in the history
These days we regard transactions with one confirmation to be
'Confirmed'.
Waiting for 6 confirmations is a recommendation but should not
keep the transaction shown as unconfirmed.

Misc code sanity:

- Merge maturity/status enums, they had become completely disjunct
- 'confirmed' flag is now called 'countsForBalance' for clarity
  • Loading branch information
laanwj committed Feb 28, 2014
1 parent 7ac375d commit f642fd9
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 128 deletions.
59 changes: 31 additions & 28 deletions src/qt/transactionrecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
(wtx.IsCoinBase() ? 1 : 0),
wtx.nTimeReceived,
idx);
status.confirmed = wtx.IsTrusted();
status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = chainActive.Height();

Expand All @@ -181,52 +181,55 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.open_for = wtx.nLockTime;
}
}
else
{
if (status.depth < 0)
{
status.status = TransactionStatus::Conflicted;
}
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
{
status.status = TransactionStatus::Offline;
}
else if (status.depth < NumConfirmations)
{
status.status = TransactionStatus::Unconfirmed;
}
else
{
status.status = TransactionStatus::HaveConfirmations;
}
}

// For generated transactions, determine maturity
if(type == TransactionRecord::Generated)
else if(type == TransactionRecord::Generated)
{
int64_t nCredit = wtx.GetCredit(true);
if (nCredit == 0)
if (wtx.GetBlocksToMaturity() > 0)
{
status.maturity = TransactionStatus::Immature;
status.status = TransactionStatus::Immature;

if (wtx.IsInMainChain())
{
status.matures_in = wtx.GetBlocksToMaturity();

// Check if the block was requested by anyone
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
status.maturity = TransactionStatus::MaturesWarning;
status.status = TransactionStatus::MaturesWarning;
}
else
{
status.maturity = TransactionStatus::NotAccepted;
status.status = TransactionStatus::NotAccepted;
}
}
else
{
status.maturity = TransactionStatus::Mature;
status.status = TransactionStatus::Confirmed;
}
}
else
{
if (status.depth < 0)
{
status.status = TransactionStatus::Conflicted;
}
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
{
status.status = TransactionStatus::Offline;
}
else if (status.depth == 0)
{
status.status = TransactionStatus::Unconfirmed;
}
else if (status.depth < RecommendedNumConfirmations)
{
status.status = TransactionStatus::Confirming;
}
else
{
status.status = TransactionStatus::Confirmed;
}
}

}

bool TransactionRecord::statusUpdateNeeded()
Expand Down
37 changes: 18 additions & 19 deletions src/qt/transactionrecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,32 @@ class TransactionStatus
{
public:
TransactionStatus():
confirmed(false), sortKey(""), maturity(Mature),
countsForBalance(false), sortKey(""),
matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1)
{ }

enum Maturity
{
Immature,
Mature,
MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */
NotAccepted
};

enum Status {
OpenUntilDate,
OpenUntilBlock,
Offline,
Unconfirmed,
HaveConfirmations,
Conflicted
Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/
/// Normal (sent/received) transactions
OpenUntilDate, /**< Transaction not yet final, waiting for date */
OpenUntilBlock, /**< Transaction not yet final, waiting for block */
Offline, /**< Not sent to any other nodes **/
Unconfirmed, /**< Not yet mined into a block **/
Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/
Conflicted, /**< Conflicts with other transaction or mempool **/
/// Generated (mined) transactions
Immature, /**< Mined but waiting for maturity */
MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */
NotAccepted /**< Mined but not accepted */
};

bool confirmed;
/// Transaction counts towards available balance
bool countsForBalance;
/// Sorting key based on status
std::string sortKey;

/** @name Generated (mined) transactions
@{*/
Maturity maturity;
int matures_in;
/**@}*/

Expand Down Expand Up @@ -79,8 +78,8 @@ class TransactionRecord
SendToSelf
};

/** Number of confirmation needed for transaction */
static const int NumConfirmations = 6;
/** Number of confirmation recommended for accepting a transaction */
static const int RecommendedNumConfirmations = 6;

TransactionRecord():
hash(), time(0), type(Other), address(""), debit(0), credit(0), idx(0)
Expand Down
143 changes: 62 additions & 81 deletions src/qt/transactiontablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,45 +285,38 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
{
QString status;

if(wtx->type == TransactionRecord::Generated)
switch(wtx->status.status)
{
switch(wtx->status.maturity)
{
case TransactionStatus::Immature:
status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
break;
case TransactionStatus::Mature:
status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
break;
case TransactionStatus::MaturesWarning:
status = tr("This block was not received by any other nodes and will probably not be accepted!");
break;
case TransactionStatus::NotAccepted:
status = tr("Generated but not accepted");
break;
}
} else {
switch(wtx->status.status)
{
case TransactionStatus::OpenUntilBlock:
status = tr("Open for %n more block(s)","",wtx->status.open_for);
break;
case TransactionStatus::OpenUntilDate:
status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
break;
case TransactionStatus::Offline:
status = tr("Offline");
break;
case TransactionStatus::Unconfirmed:
status = tr("Unconfirmed (%1 of %2 confirmations)").arg(wtx->status.depth).arg(TransactionRecord::NumConfirmations);
break;
case TransactionStatus::HaveConfirmations:
status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
break;
case TransactionStatus::Conflicted:
status = tr("Conflicted");
break;
}
case TransactionStatus::OpenUntilBlock:
status = tr("Open for %n more block(s)","",wtx->status.open_for);
break;
case TransactionStatus::OpenUntilDate:
status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
break;
case TransactionStatus::Offline:
status = tr("Offline");
break;
case TransactionStatus::Unconfirmed:
status = tr("Unconfirmed");
break;
case TransactionStatus::Confirming:
status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
break;
case TransactionStatus::Confirmed:
status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
break;
case TransactionStatus::Conflicted:
status = tr("Conflicted");
break;
case TransactionStatus::Immature:
status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
break;
case TransactionStatus::MaturesWarning:
status = tr("This block was not received by any other nodes and will probably not be accepted!");
break;
case TransactionStatus::NotAccepted:
status = tr("Generated but not accepted");
break;
}

return status;
Expand Down Expand Up @@ -441,7 +434,7 @@ QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool
QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit);
if(showUnconfirmed)
{
if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature)
if(!wtx->status.countsForBalance)
{
str = QString("[") + str + QString("]");
}
Expand All @@ -451,46 +444,36 @@ QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool

QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) const
{
if(wtx->type == TransactionRecord::Generated)
{
switch(wtx->status.maturity)
{
case TransactionStatus::Immature: {
int total = wtx->status.depth + wtx->status.matures_in;
int part = (wtx->status.depth * 4 / total) + 1;
return QIcon(QString(":/icons/transaction_%1").arg(part));
}
case TransactionStatus::Mature:
return QIcon(":/icons/transaction_confirmed");
case TransactionStatus::MaturesWarning:
case TransactionStatus::NotAccepted:
return QIcon(":/icons/transaction_0");
}
}
else
switch(wtx->status.status)
{
switch(wtx->status.status)
case TransactionStatus::OpenUntilBlock:
case TransactionStatus::OpenUntilDate:
return QColor(64,64,255);
case TransactionStatus::Offline:
return QColor(192,192,192);
case TransactionStatus::Unconfirmed:
return QIcon(":/icons/transaction_0");
case TransactionStatus::Confirming:
switch(wtx->status.depth)
{
case TransactionStatus::OpenUntilBlock:
case TransactionStatus::OpenUntilDate:
return QColor(64,64,255);
case TransactionStatus::Offline:
return QColor(192,192,192);
case TransactionStatus::Unconfirmed:
switch(wtx->status.depth)
{
case 0: return QIcon(":/icons/transaction_0");
case 1: return QIcon(":/icons/transaction_1");
case 2: return QIcon(":/icons/transaction_2");
case 3: return QIcon(":/icons/transaction_3");
case 4: return QIcon(":/icons/transaction_4");
default: return QIcon(":/icons/transaction_5");
};
case TransactionStatus::HaveConfirmations:
return QIcon(":/icons/transaction_confirmed");
case TransactionStatus::Conflicted:
return QIcon(":/icons/transaction_conflicted");
case 1: return QIcon(":/icons/transaction_1");
case 2: return QIcon(":/icons/transaction_2");
case 3: return QIcon(":/icons/transaction_3");
case 4: return QIcon(":/icons/transaction_4");
default: return QIcon(":/icons/transaction_5");
};
case TransactionStatus::Confirmed:
return QIcon(":/icons/transaction_confirmed");
case TransactionStatus::Conflicted:
return QIcon(":/icons/transaction_conflicted");
case TransactionStatus::Immature: {
int total = wtx->status.depth + wtx->status.matures_in;
int part = (wtx->status.depth * 4 / total) + 1;
return QIcon(QString(":/icons/transaction_%1").arg(part));
}
case TransactionStatus::MaturesWarning:
case TransactionStatus::NotAccepted:
return QIcon(":/icons/transaction_0");
}
return QColor(0,0,0);
}
Expand Down Expand Up @@ -557,8 +540,8 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case Qt::TextAlignmentRole:
return column_alignments[index.column()];
case Qt::ForegroundRole:
// Non-confirmed transactions are grey
if(!rec->status.confirmed)
// Non-confirmed (but not immature) as transactions are grey
if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)
{
return COLOR_UNCONFIRMED;
}
Expand Down Expand Up @@ -586,9 +569,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case TxIDRole:
return rec->getTxID();
case ConfirmedRole:
// Return True if transaction counts for balance
return rec->status.confirmed && !(rec->type == TransactionRecord::Generated &&
rec->status.maturity != TransactionStatus::Mature);
return rec->status.countsForBalance;
case FormattedAmountRole:
return formatTxAmount(rec, false);
case StatusRole:
Expand Down

0 comments on commit f642fd9

Please sign in to comment.