123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- // ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
- #include "transactionrecord.h"
- #include "wallet.h"
- #include "base58.h"
- bool TransactionRecord::showTransaction(const CWalletTx &wtx)
- {
- if (wtx.IsCoinBase())
- {
- // Ensures we show generated coins / mined transactions at depth 1
- if (!wtx.IsInMainChain())
- {
- return false;
- }
- }
- return true;
- }
- 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;
- uint256 hash = wtx.GetHash(), hashPrev = 0;
- std::map<std::string, std::string> mapValue = wtx.mapValue;
- if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake())
- {
- // Credit
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- {
- if(wallet->IsMine(txout))
- {
- TransactionRecord sub(hash, nTime);
- CTxDestination address;
- sub.idx = parts.size(); // sequence number
- sub.credit = txout.nValue;
- if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
- {
- // Received by Ecoin Address
- sub.type = TransactionRecord::RecvWithAddress;
- sub.address = CEcoinAddress(address).ToString();
- }
- else
- {
- // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
- sub.type = TransactionRecord::RecvFromOther;
- sub.address = mapValue["from"];
- }
- if (wtx.IsCoinBase())
- {
- // Generated (proof-of-work)
- sub.type = TransactionRecord::Generated;
- }
- if (wtx.IsCoinStake())
- {
- // Generated (proof-of-stake)
- if (hashPrev == hash)
- continue; // last coinstake output
- sub.type = TransactionRecord::Generated;
- sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit;
- hashPrev = hash;
- }
- parts.append(sub);
- }
- }
- }
- else
- {
- bool fAllFromMe = true;
- BOOST_FOREACH(const CTxIn& txin, wtx.vin)
- fAllFromMe = fAllFromMe && wallet->IsMine(txin);
- bool fAllToMe = true;
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- fAllToMe = fAllToMe && wallet->IsMine(txout);
- if (fAllFromMe && fAllToMe)
- {
- // Payment to self
- int64 nChange = wtx.GetChange();
- parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
- -(nDebit - nChange), nCredit - nChange));
- }
- else if (fAllFromMe)
- {
- // Debit
- int64 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();
- if(wallet->IsMine(txout))
- {
- continue;
- }
- CTxDestination address;
- if (ExtractDestination(txout.scriptPubKey, address))
- {
- // Sent to Ecoin Address
- sub.type = TransactionRecord::SendToAddress;
- sub.address = CEcoinAddress(address).ToString();
- }
- else
- {
- // Sent to IP, or other non-address transaction like OP_EVAL
- sub.type = TransactionRecord::SendToOther;
- sub.address = mapValue["to"];
- }
- int64 nValue = txout.nValue;
- /* Add fee to first output */
- if (nTxFee > 0)
- {
- nValue += nTxFee;
- nTxFee = 0;
- }
- sub.debit = -nValue;
- parts.append(sub);
- }
- }
- else
- {
- // Mixed debit transaction, can't break down payees
- parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
- }
- }
- return parts;
- }
- void TransactionRecord::updateStatus(const CWalletTx &wtx)
- {
- // Determine transaction status
- CBlockIndex* pindex = NULL;
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
- if (mi != mapBlockIndex.end())
- pindex = (*mi).second;
- // Sort order, unrecorded transactions sort to the top
- status.sortKey = strprintf("%010d-%01d-%010u-%03d",
- (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
- (wtx.IsCoinBase() ? 1 : 0),
- wtx.nTimeReceived,
- idx);
- status.confirmed = wtx.IsTrusted();
- status.depth = wtx.GetDepthInMainChain();
- status.cur_num_blocks = nBestHeight;
- if (!wtx.IsFinal())
- {
- if (wtx.nLockTime < LOCKTIME_THRESHOLD)
- {
- status.status = TransactionStatus::OpenUntilBlock;
- status.open_for = nBestHeight - wtx.nLockTime;
- }
- else
- {
- status.status = TransactionStatus::OpenUntilDate;
- 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)
- {
- int64 nCredit = wtx.GetCredit(true);
- if (nCredit == 0)
- {
- status.maturity = 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;
- }
- else
- {
- status.maturity = TransactionStatus::NotAccepted;
- }
- }
- else
- {
- status.maturity = TransactionStatus::Mature;
- }
- }
- }
- bool TransactionRecord::statusUpdateNeeded()
- {
- return status.cur_num_blocks != nBestHeight;
- }
- std::string TransactionRecord::getTxID()
- {
- return hash.ToString() + strprintf("-%03d", idx);
- }
|