aboutsummaryrefslogtreecommitdiff
path: root/src/qt/transactionrecord.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/transactionrecord.cpp')
-rw-r--r--src/qt/transactionrecord.cpp153
1 files changed, 91 insertions, 62 deletions
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 160973638..7f1db58e5 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -1,7 +1,18 @@
+// Copyright (c) 2011-2014 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "transactionrecord.h"
-#include "wallet.h"
#include "base58.h"
+#include "consensus/consensus.h"
+#include "main.h"
+#include "timedata.h"
+#include "wallet/wallet.h"
+
+#include <stdint.h>
+
+#include <boost/foreach.hpp>
/* Return positive answer if transaction should be shown in list.
*/
@@ -9,18 +20,8 @@ bool TransactionRecord::showTransaction(const CWalletTx &wtx)
{
if (wtx.IsCoinBase())
{
- // Don't show generated coin until confirmed by at least one block after it
- // so we don't get the user's hopes up until it looks like it's probably accepted.
- //
- // It is not an error when generated blocks are not accepted. By design,
- // some percentage of blocks, like 10% or more, will end up not accepted.
- // This is the normal mechanism by which the network copes with latency.
- //
- // We display regular transactions right away before any confirmation
- // because they can always get into some block eventually. Generated coins
- // are special because if their block is not accepted, they are not valid.
- //
- if (wtx.GetDepthInMainChain() < 2)
+ // Ensures we show generated coins / mined transactions at depth 1
+ if (!wtx.IsInMainChain())
{
return false;
}
@@ -34,10 +35,10 @@ bool TransactionRecord::showTransaction(const CWalletTx &wtx)
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
QList<TransactionRecord> parts;
- int64 nTime = wtx.GetTxTime();
- int64 nCredit = wtx.GetCredit(true);
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
+ int64_t nTime = wtx.GetTxTime();
+ CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
+ CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
+ CAmount nNet = nCredit - nDebit;
uint256 hash = wtx.GetHash();
std::map<std::string, std::string> mapValue = wtx.mapValue;
@@ -48,18 +49,15 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
//
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
- if(wallet->IsMine(txout))
+ isminetype mine = wallet->IsMine(txout);
+ if(mine)
{
TransactionRecord sub(hash, nTime);
CTxDestination address;
sub.idx = parts.size(); // sequence number
sub.credit = txout.nValue;
- if (wtx.IsCoinBase())
- {
- // Generated
- sub.type = TransactionRecord::Generated;
- }
- else if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
+ sub.involvesWatchAddress = mine == ISMINE_WATCH_ONLY;
+ if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
{
// Received by Bitcoin Address
sub.type = TransactionRecord::RecvWithAddress;
@@ -71,6 +69,11 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
sub.type = TransactionRecord::RecvFromOther;
sub.address = mapValue["from"];
}
+ if (wtx.IsCoinBase())
+ {
+ // Generated
+ sub.type = TransactionRecord::Generated;
+ }
parts.append(sub);
}
@@ -78,34 +81,45 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
}
else
{
- bool fAllFromMe = true;
+ bool involvesWatchAddress = false;
+ isminetype fAllFromMe = ISMINE_SPENDABLE;
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
- fAllFromMe = fAllFromMe && wallet->IsMine(txin);
+ {
+ isminetype mine = wallet->IsMine(txin);
+ if(mine == ISMINE_WATCH_ONLY) involvesWatchAddress = true;
+ if(fAllFromMe > mine) fAllFromMe = mine;
+ }
- bool fAllToMe = true;
+ isminetype fAllToMe = ISMINE_SPENDABLE;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- fAllToMe = fAllToMe && wallet->IsMine(txout);
+ {
+ isminetype mine = wallet->IsMine(txout);
+ if(mine == ISMINE_WATCH_ONLY) involvesWatchAddress = true;
+ if(fAllToMe > mine) fAllToMe = mine;
+ }
if (fAllFromMe && fAllToMe)
{
// Payment to self
- int64 nChange = wtx.GetChange();
+ CAmount nChange = wtx.GetChange();
parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
-(nDebit - nChange), nCredit - nChange));
+ parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument
}
else if (fAllFromMe)
{
//
// Debit
//
- int64 nTxFee = nDebit - wtx.GetValueOut();
+ CAmount nTxFee = nDebit - wtx.GetValueOut();
for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
{
const CTxOut& txout = wtx.vout[nOut];
TransactionRecord sub(hash, nTime);
sub.idx = parts.size();
+ sub.involvesWatchAddress = involvesWatchAddress;
if(wallet->IsMine(txout))
{
@@ -128,7 +142,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
sub.address = mapValue["to"];
}
- int64 nValue = txout.nValue;
+ CAmount nValue = txout.nValue;
/* Add fee to first output */
if (nTxFee > 0)
{
@@ -146,6 +160,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
// Mixed debit transaction, can't break down payees
//
parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
+ parts.last().involvesWatchAddress = involvesWatchAddress;
}
}
@@ -154,11 +169,12 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
+ AssertLockHeld(cs_main);
// Determine transaction status
// Find the block the tx is in
CBlockIndex* pindex = NULL;
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
+ BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
if (mi != mapBlockIndex.end())
pindex = (*mi).second;
@@ -168,16 +184,16 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
(wtx.IsCoinBase() ? 1 : 0),
wtx.nTimeReceived,
idx);
- status.confirmed = wtx.IsConfirmed();
+ status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
status.depth = wtx.GetDepthInMainChain();
- status.cur_num_blocks = nBestHeight;
+ status.cur_num_blocks = chainActive.Height();
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx, chainActive.Height() + 1))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
{
status.status = TransactionStatus::OpenUntilBlock;
- status.open_for = nBestHeight - wtx.nLockTime;
+ status.open_for = wtx.nLockTime - chainActive.Height();
}
else
{
@@ -185,29 +201,12 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.open_for = wtx.nLockTime;
}
}
- 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 nCredit = wtx.GetCredit(true);
- if (nCredit == 0)
+ if (wtx.GetBlocksToMaturity() > 0)
{
- status.maturity = TransactionStatus::Immature;
+ status.status = TransactionStatus::Immature;
if (wtx.IsInMainChain())
{
@@ -215,27 +214,57 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
// 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()
{
- return status.cur_num_blocks != nBestHeight;
+ AssertLockHeld(cs_main);
+ return status.cur_num_blocks != chainActive.Height();
+}
+
+QString TransactionRecord::getTxID() const
+{
+ return formatSubTxId(hash, idx);
}
-std::string TransactionRecord::getTxID()
+QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout)
{
- return hash.ToString() + strprintf("-%03d", idx);
+ return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout));
}