Page MenuHomePhabricator

No OneTemporary

diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 0ad123f39..c5f8fb6a9 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1,665 +1,645 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "walletmodel.h"
#include "addresstablemodel.h"
#include "guiconstants.h"
#include "recentrequeststablemodel.h"
#include "transactiontablemodel.h"
#include "base58.h"
#include "db.h"
#include "keystore.h"
#include "main.h"
#include "sync.h"
#include "ui_interface.h"
#include "wallet.h"
#include "walletdb.h" // for BackupWallet
#include <stdint.h>
#include <QDebug>
#include <QSet>
#include <QTimer>
using namespace std;
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
transactionTableModel(0),
recentRequestsTableModel(0),
cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0),
- cachedNumTransactions(0),
cachedEncryptionStatus(Unencrypted),
cachedNumBlocks(0)
{
fProcessingQueuedTransactions = false;
addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this);
recentRequestsTableModel = new RecentRequestsTableModel(wallet, this);
// This timer will be fired repeatedly to update the balance
pollTimer = new QTimer(this);
connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
pollTimer->start(MODEL_UPDATE_DELAY);
subscribeToCoreSignals();
}
WalletModel::~WalletModel()
{
unsubscribeFromCoreSignals();
}
qint64 WalletModel::getBalance(const CCoinControl *coinControl) const
{
if (coinControl)
{
qint64 nBalance = 0;
std::vector<COutput> vCoins;
wallet->AvailableCoins(vCoins, true, coinControl);
BOOST_FOREACH(const COutput& out, vCoins)
if(out.fSpendable)
nBalance += out.tx->vout[out.i].nValue;
return nBalance;
}
return wallet->GetBalance();
}
qint64 WalletModel::getUnconfirmedBalance() const
{
return wallet->GetUnconfirmedBalance();
}
qint64 WalletModel::getImmatureBalance() const
{
return wallet->GetImmatureBalance();
}
qint64 WalletModel::getWatchBalance() const
{
return wallet->GetWatchOnlyBalance();
}
qint64 WalletModel::getWatchUnconfirmedBalance() const
{
return wallet->GetUnconfirmedWatchOnlyBalance();
}
qint64 WalletModel::getWatchImmatureBalance() const
{
return wallet->GetImmatureWatchOnlyBalance();
}
-int WalletModel::getNumTransactions() const
-{
- int numTransactions = 0;
- {
- LOCK(wallet->cs_wallet);
- // the size of mapWallet contains the number of unique transaction IDs
- // (e.g. payments to yourself generate 2 transactions, but both share the same transaction ID)
- numTransactions = wallet->mapWallet.size();
- }
- return numTransactions;
-}
-
void WalletModel::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
if(cachedEncryptionStatus != newEncryptionStatus)
emit encryptionStatusChanged(newEncryptionStatus);
}
void WalletModel::pollBalanceChanged()
{
// Get required locks upfront. This avoids the GUI from getting stuck on
// periodical polls if the core is holding the locks for a longer time -
// for example, during a wallet rescan.
TRY_LOCK(cs_main, lockMain);
if(!lockMain)
return;
TRY_LOCK(wallet->cs_wallet, lockWallet);
if(!lockWallet)
return;
if(chainActive.Height() != cachedNumBlocks)
{
// Balance and number of transactions might have changed
cachedNumBlocks = chainActive.Height();
checkBalanceChanged();
if(transactionTableModel)
transactionTableModel->updateConfirmations();
}
}
void WalletModel::checkBalanceChanged()
{
qint64 newBalance = getBalance();
qint64 newUnconfirmedBalance = getUnconfirmedBalance();
qint64 newImmatureBalance = getImmatureBalance();
qint64 newWatchOnlyBalance = getWatchBalance();
qint64 newWatchUnconfBalance = getWatchUnconfirmedBalance();
qint64 newWatchImmatureBalance = getWatchImmatureBalance();
if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance ||
cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance)
{
cachedBalance = newBalance;
cachedUnconfirmedBalance = newUnconfirmedBalance;
cachedImmatureBalance = newImmatureBalance;
cachedWatchOnlyBalance = newWatchOnlyBalance;
cachedWatchUnconfBalance = newWatchUnconfBalance;
cachedWatchImmatureBalance = newWatchImmatureBalance;
emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance,
newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance);
}
}
void WalletModel::updateTransaction(const QString &hash, int status)
{
if(transactionTableModel)
transactionTableModel->updateTransaction(hash, status);
// Balance and number of transactions might have changed
checkBalanceChanged();
-
- int newNumTransactions = getNumTransactions();
- if(cachedNumTransactions != newNumTransactions)
- {
- cachedNumTransactions = newNumTransactions;
- emit numTransactionsChanged(newNumTransactions);
- }
}
void WalletModel::updateAddressBook(const QString &address, const QString &label,
bool isMine, const QString &purpose, int status)
{
if(addressTableModel)
addressTableModel->updateEntry(address, label, isMine, purpose, status);
}
bool WalletModel::validateAddress(const QString &address)
{
CBitcoinAddress addressParsed(address.toStdString());
return addressParsed.IsValid();
}
WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl)
{
qint64 total = 0;
QList<SendCoinsRecipient> recipients = transaction.getRecipients();
std::vector<std::pair<CScript, int64_t> > vecSend;
if(recipients.empty())
{
return OK;
}
QSet<QString> setAddress; // Used to detect duplicates
int nAddresses = 0;
// Pre-check input data for validity
foreach(const SendCoinsRecipient &rcp, recipients)
{
if (rcp.paymentRequest.IsInitialized())
{ // PaymentRequest...
int64_t subtotal = 0;
const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
for (int i = 0; i < details.outputs_size(); i++)
{
const payments::Output& out = details.outputs(i);
if (out.amount() <= 0) continue;
subtotal += out.amount();
const unsigned char* scriptStr = (const unsigned char*)out.script().data();
CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, out.amount()));
}
if (subtotal <= 0)
{
return InvalidAmount;
}
total += subtotal;
}
else
{ // User-entered bitcoin address / amount:
if(!validateAddress(rcp.address))
{
return InvalidAddress;
}
if(rcp.amount <= 0)
{
return InvalidAmount;
}
setAddress.insert(rcp.address);
++nAddresses;
CScript scriptPubKey;
scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, rcp.amount));
total += rcp.amount;
}
}
if(setAddress.size() != nAddresses)
{
return DuplicateAddress;
}
qint64 nBalance = getBalance(coinControl);
if(total > nBalance)
{
return AmountExceedsBalance;
}
{
LOCK2(cs_main, wallet->cs_wallet);
transaction.newPossibleKeyChange(wallet);
int64_t nFeeRequired = 0;
std::string strFailReason;
CWalletTx *newTx = transaction.getTransaction();
CReserveKey *keyChange = transaction.getPossibleKeyChange();
bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl);
transaction.setTransactionFee(nFeeRequired);
if(!fCreated)
{
if((total + nFeeRequired) > nBalance)
{
return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
emit message(tr("Send Coins"), QString::fromStdString(strFailReason),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
}
return SendCoinsReturn(OK);
}
WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction)
{
QByteArray transaction_array; /* store serialized transaction */
{
LOCK2(cs_main, wallet->cs_wallet);
CWalletTx *newTx = transaction.getTransaction();
// Store PaymentRequests in wtx.vOrderForm in wallet.
foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
if (rcp.paymentRequest.IsInitialized())
{
std::string key("PaymentRequest");
std::string value;
rcp.paymentRequest.SerializeToString(&value);
newTx->vOrderForm.push_back(make_pair(key, value));
}
else if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString()));
}
CReserveKey *keyChange = transaction.getPossibleKeyChange();
if(!wallet->CommitTransaction(*newTx, *keyChange))
return TransactionCommitFailed;
CTransaction* t = (CTransaction*)newTx;
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << *t;
transaction_array.append(&(ssTx[0]), ssTx.size());
}
// Add addresses / update labels that we've sent to to the address book,
// and emit coinsSent signal for each recipient
foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
// Don't touch the address book when we have a payment request
if (!rcp.paymentRequest.IsInitialized())
{
std::string strAddress = rcp.address.toStdString();
CTxDestination dest = CBitcoinAddress(strAddress).Get();
std::string strLabel = rcp.label.toStdString();
{
LOCK(wallet->cs_wallet);
std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
// Check if we have a new address or an updated label
if (mi == wallet->mapAddressBook.end())
{
wallet->SetAddressBook(dest, strLabel, "send");
}
else if (mi->second.name != strLabel)
{
wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
}
}
}
emit coinsSent(wallet, rcp, transaction_array);
}
return SendCoinsReturn(OK);
}
OptionsModel *WalletModel::getOptionsModel()
{
return optionsModel;
}
AddressTableModel *WalletModel::getAddressTableModel()
{
return addressTableModel;
}
TransactionTableModel *WalletModel::getTransactionTableModel()
{
return transactionTableModel;
}
RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel()
{
return recentRequestsTableModel;
}
WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
{
if(!wallet->IsCrypted())
{
return Unencrypted;
}
else if(wallet->IsLocked())
{
return Locked;
}
else
{
return Unlocked;
}
}
bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase)
{
if(encrypted)
{
// Encrypt
return wallet->EncryptWallet(passphrase);
}
else
{
// Decrypt -- TODO; not supported yet
return false;
}
}
bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
{
if(locked)
{
// Lock
return wallet->Lock();
}
else
{
// Unlock
return wallet->Unlock(passPhrase);
}
}
bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
{
bool retval;
{
LOCK(wallet->cs_wallet);
wallet->Lock(); // Make sure wallet is locked before attempting pass change
retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
}
return retval;
}
bool WalletModel::backupWallet(const QString &filename)
{
return BackupWallet(*wallet, filename.toLocal8Bit().data());
}
// Handlers for core signals
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
{
qDebug() << "NotifyKeyStoreStatusChanged";
QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
}
static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
const CTxDestination &address, const std::string &label, bool isMine,
const std::string &purpose, ChangeType status)
{
QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString());
QString strLabel = QString::fromStdString(label);
QString strPurpose = QString::fromStdString(purpose);
qDebug() << "NotifyAddressBookChanged : " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
Q_ARG(QString, strAddress),
Q_ARG(QString, strLabel),
Q_ARG(bool, isMine),
Q_ARG(QString, strPurpose),
Q_ARG(int, status));
}
// queue notifications to show a non freezing progress dialog e.g. for rescan
static bool fQueueNotifications = false;
static std::vector<std::pair<uint256, ChangeType> > vQueueNotifications;
static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
{
if (fQueueNotifications)
{
vQueueNotifications.push_back(make_pair(hash, status));
return;
}
QString strHash = QString::fromStdString(hash.GetHex());
qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection,
Q_ARG(QString, strHash),
Q_ARG(int, status));
}
static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
{
// emits signal "showProgress"
QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(title)),
Q_ARG(int, nProgress));
if (nProgress == 0)
fQueueNotifications = true;
if (nProgress == 100)
{
fQueueNotifications = false;
if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
QMetaObject::invokeMethod(walletmodel, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
{
if (vQueueNotifications.size() - i <= 10)
QMetaObject::invokeMethod(walletmodel, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
NotifyTransactionChanged(walletmodel, NULL, vQueueNotifications[i].first, vQueueNotifications[i].second);
}
std::vector<std::pair<uint256, ChangeType> >().swap(vQueueNotifications); // clear
}
}
void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
}
void WalletModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from wallet
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
}
// WalletModel::UnlockContext implementation
WalletModel::UnlockContext WalletModel::requestUnlock()
{
bool was_locked = getEncryptionStatus() == Locked;
if(was_locked)
{
// Request UI to unlock wallet
emit requireUnlock();
}
// If wallet is still locked, unlock was failed or cancelled, mark context as invalid
bool valid = getEncryptionStatus() != Locked;
return UnlockContext(this, valid, was_locked);
}
WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock):
wallet(wallet),
valid(valid),
relock(relock)
{
}
WalletModel::UnlockContext::~UnlockContext()
{
if(valid && relock)
{
wallet->setWalletLocked(true);
}
}
void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs)
{
// Transfer context; old object no longer relocks wallet
*this = rhs;
rhs.relock = false;
}
bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
{
return wallet->GetPubKey(address, vchPubKeyOut);
}
// returns a list of COutputs from COutPoints
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
{
LOCK2(cs_main, wallet->cs_wallet);
BOOST_FOREACH(const COutPoint& outpoint, vOutpoints)
{
if (!wallet->mapWallet.count(outpoint.hash)) continue;
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
if (nDepth < 0) continue;
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true);
vOutputs.push_back(out);
}
}
bool WalletModel::isSpent(const COutPoint& outpoint) const
{
LOCK2(cs_main, wallet->cs_wallet);
return wallet->IsSpent(outpoint.hash, outpoint.n);
}
// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
{
std::vector<COutput> vCoins;
wallet->AvailableCoins(vCoins);
LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet
std::vector<COutPoint> vLockedCoins;
wallet->ListLockedCoins(vLockedCoins);
// add locked coins
BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins)
{
if (!wallet->mapWallet.count(outpoint.hash)) continue;
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
if (nDepth < 0) continue;
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true);
vCoins.push_back(out);
}
BOOST_FOREACH(const COutput& out, vCoins)
{
COutput cout = out;
while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0]))
{
if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break;
cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true);
}
CTxDestination address;
if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
continue;
mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out);
}
}
bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
{
LOCK2(cs_main, wallet->cs_wallet);
return wallet->IsLockedCoin(hash, n);
}
void WalletModel::lockCoin(COutPoint& output)
{
LOCK2(cs_main, wallet->cs_wallet);
wallet->LockCoin(output);
}
void WalletModel::unlockCoin(COutPoint& output)
{
LOCK2(cs_main, wallet->cs_wallet);
wallet->UnlockCoin(output);
}
void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
{
LOCK2(cs_main, wallet->cs_wallet);
wallet->ListLockedCoins(vOutpts);
}
void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
{
LOCK(wallet->cs_wallet);
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item2, item.second.destdata)
if (item2.first.size() > 2 && item2.first.substr(0,2) == "rr") // receive request
vReceiveRequests.push_back(item2.second);
}
bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
{
CTxDestination dest = CBitcoinAddress(sAddress).Get();
std::stringstream ss;
ss << nId;
std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
LOCK(wallet->cs_wallet);
if (sRequest.empty())
return wallet->EraseDestData(dest, key);
else
return wallet->AddDestData(dest, key, sRequest);
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 2bb91d85a..2a74a6aa7 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -1,265 +1,260 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef WALLETMODEL_H
#define WALLETMODEL_H
#include "paymentrequestplus.h"
#include "walletmodeltransaction.h"
#include "allocators.h" /* for SecureString */
#include <map>
#include <vector>
#include <QObject>
class AddressTableModel;
class OptionsModel;
class RecentRequestsTableModel;
class TransactionTableModel;
class WalletModelTransaction;
class CCoinControl;
class CKeyID;
class COutPoint;
class COutput;
class CPubKey;
class CWallet;
class uint256;
QT_BEGIN_NAMESPACE
class QTimer;
QT_END_NAMESPACE
class SendCoinsRecipient
{
public:
explicit SendCoinsRecipient() : amount(0), nVersion(SendCoinsRecipient::CURRENT_VERSION) { }
explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message):
address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
// If from an insecure payment request, this is used for storing
// the addresses, e.g. address-A<br />address-B<br />address-C.
// Info: As we don't need to process addresses in here when using
// payment requests, we can abuse it for displaying an address list.
// Todo: This is a hack, should be replaced with a cleaner solution!
QString address;
QString label;
qint64 amount;
// If from a payment request, this is used for storing the memo
QString message;
// If from a payment request, paymentRequest.IsInitialized() will be true
PaymentRequestPlus paymentRequest;
// Empty if no authentication or invalid signature/cert/etc.
QString authenticatedMerchant;
static const int CURRENT_VERSION = 1;
int nVersion;
IMPLEMENT_SERIALIZE
(
SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(this);
std::string sAddress = pthis->address.toStdString();
std::string sLabel = pthis->label.toStdString();
std::string sMessage = pthis->message.toStdString();
std::string sPaymentRequest;
if (!fRead && pthis->paymentRequest.IsInitialized())
pthis->paymentRequest.SerializeToString(&sPaymentRequest);
std::string sAuthenticatedMerchant = pthis->authenticatedMerchant.toStdString();
READWRITE(pthis->nVersion);
nVersion = pthis->nVersion;
READWRITE(sAddress);
READWRITE(sLabel);
READWRITE(amount);
READWRITE(sMessage);
READWRITE(sPaymentRequest);
READWRITE(sAuthenticatedMerchant);
if (fRead)
{
pthis->address = QString::fromStdString(sAddress);
pthis->label = QString::fromStdString(sLabel);
pthis->message = QString::fromStdString(sMessage);
if (!sPaymentRequest.empty())
pthis->paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
pthis->authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
}
)
};
/** Interface to Bitcoin wallet from Qt view code. */
class WalletModel : public QObject
{
Q_OBJECT
public:
explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0);
~WalletModel();
enum StatusCode // Returned by sendCoins
{
OK,
InvalidAmount,
InvalidAddress,
AmountExceedsBalance,
AmountWithFeeExceedsBalance,
DuplicateAddress,
TransactionCreationFailed, // Error returned when wallet is still locked
TransactionCommitFailed
};
enum EncryptionStatus
{
Unencrypted, // !wallet->IsCrypted()
Locked, // wallet->IsCrypted() && wallet->IsLocked()
Unlocked // wallet->IsCrypted() && !wallet->IsLocked()
};
OptionsModel *getOptionsModel();
AddressTableModel *getAddressTableModel();
TransactionTableModel *getTransactionTableModel();
RecentRequestsTableModel *getRecentRequestsTableModel();
qint64 getBalance(const CCoinControl *coinControl = NULL) const;
qint64 getUnconfirmedBalance() const;
qint64 getImmatureBalance() const;
qint64 getWatchBalance() const;
qint64 getWatchUnconfirmedBalance() const;
qint64 getWatchImmatureBalance() const;
- int getNumTransactions() const;
EncryptionStatus getEncryptionStatus() const;
bool processingQueuedTransactions() { return fProcessingQueuedTransactions; }
// Check address for validity
bool validateAddress(const QString &address);
// Return status record for SendCoins, contains error id + information
struct SendCoinsReturn
{
SendCoinsReturn(StatusCode status = OK):
status(status) {}
StatusCode status;
};
// prepare transaction for getting txfee before sending coins
SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl = NULL);
// Send coins to a list of recipients
SendCoinsReturn sendCoins(WalletModelTransaction &transaction);
// Wallet encryption
bool setWalletEncrypted(bool encrypted, const SecureString &passphrase);
// Passphrase only needed when unlocking
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
// Wallet backup
bool backupWallet(const QString &filename);
// RAI object for unlocking wallet, returned by requestUnlock()
class UnlockContext
{
public:
UnlockContext(WalletModel *wallet, bool valid, bool relock);
~UnlockContext();
bool isValid() const { return valid; }
// Copy operator and constructor transfer the context
UnlockContext(const UnlockContext& obj) { CopyFrom(obj); }
UnlockContext& operator=(const UnlockContext& rhs) { CopyFrom(rhs); return *this; }
private:
WalletModel *wallet;
bool valid;
mutable bool relock; // mutable, as it can be set to false by copying
void CopyFrom(const UnlockContext& rhs);
};
UnlockContext requestUnlock();
bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
bool isSpent(const COutPoint& outpoint) const;
void listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const;
bool isLockedCoin(uint256 hash, unsigned int n) const;
void lockCoin(COutPoint& output);
void unlockCoin(COutPoint& output);
void listLockedCoins(std::vector<COutPoint>& vOutpts);
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
private:
CWallet *wallet;
bool fProcessingQueuedTransactions;
// Wallet has an options model for wallet-specific options
// (transaction fee, for example)
OptionsModel *optionsModel;
AddressTableModel *addressTableModel;
TransactionTableModel *transactionTableModel;
RecentRequestsTableModel *recentRequestsTableModel;
// Cache some values to be able to detect changes
qint64 cachedBalance;
qint64 cachedUnconfirmedBalance;
qint64 cachedImmatureBalance;
qint64 cachedWatchOnlyBalance;
qint64 cachedWatchUnconfBalance;
qint64 cachedWatchImmatureBalance;
- qint64 cachedNumTransactions;
EncryptionStatus cachedEncryptionStatus;
int cachedNumBlocks;
QTimer *pollTimer;
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();
void checkBalanceChanged();
signals:
// Signal that balance in wallet changed
void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance,
qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance);
- // Number of transactions in wallet changed
- void numTransactionsChanged(int count);
-
// Encryption status of wallet changed
void encryptionStatusChanged(int status);
// Signal emitted when wallet needs to be unlocked
// It is valid behaviour for listeners to keep the wallet locked after this signal;
// this means that the unlocking failed or was cancelled.
void requireUnlock();
// Fired when a message should be reported to the user
void message(const QString &title, const QString &message, unsigned int style);
// Coins sent: from wallet, to recipient, in (serialized) transaction:
void coinsSent(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction);
// Show progress dialog e.g. for rescan
void showProgress(const QString &title, int nProgress);
public slots:
/* Wallet status might have changed */
void updateStatus();
/* New transaction, or transaction changed status */
void updateTransaction(const QString &hash, int status);
/* New, updated or removed address book entry */
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
void pollBalanceChanged();
/* Needed to update fProcessingQueuedTransactions through a QueuedConnection */
void setProcessingQueuedTransactions(bool value) { fProcessingQueuedTransactions = value; }
};
#endif // WALLETMODEL_H

File Metadata

Mime Type
text/x-diff
Expires
Fri, Feb 7, 16:00 (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5082653
Default Alt Text
(32 KB)

Event Timeline