2014-02-08 22:50:24 +01:00
|
|
|
// Copyright (c) 2011-2014 The Bitcoin developers
|
2013-11-04 16:20:43 +01:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2014-11-03 16:16:40 +01:00
|
|
|
#ifndef BITCOIN_QT_WALLETMODEL_H
|
|
|
|
#define BITCOIN_QT_WALLETMODEL_H
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
#include "paymentrequestplus.h"
|
|
|
|
#include "walletmodeltransaction.h"
|
2011-11-26 07:02:04 +01:00
|
|
|
|
2012-03-24 20:07:01 +01:00
|
|
|
#include "allocators.h" /* for SecureString */
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2013-08-12 17:03:03 +02:00
|
|
|
#include <map>
|
2013-11-16 17:37:31 +01:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <QObject>
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2011-06-30 18:05:29 +02:00
|
|
|
class AddressTableModel;
|
2013-04-13 07:13:08 +02:00
|
|
|
class OptionsModel;
|
2013-11-05 18:03:05 +01:00
|
|
|
class RecentRequestsTableModel;
|
2013-12-16 22:54:02 +01:00
|
|
|
class TransactionTableModel;
|
2013-08-30 20:04:48 +02:00
|
|
|
class WalletModelTransaction;
|
2013-11-16 17:37:31 +01:00
|
|
|
|
|
|
|
class CCoinControl;
|
2013-08-12 17:03:03 +02:00
|
|
|
class CKeyID;
|
|
|
|
class COutPoint;
|
2013-11-16 17:37:31 +01:00
|
|
|
class COutput;
|
|
|
|
class CPubKey;
|
2013-04-13 07:13:08 +02:00
|
|
|
class CWallet;
|
2013-11-16 17:37:31 +01:00
|
|
|
class uint256;
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2012-07-05 17:43:28 +02:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
class QTimer;
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
2012-03-18 23:14:03 +01:00
|
|
|
class SendCoinsRecipient
|
2011-07-16 19:01:05 +02:00
|
|
|
{
|
2012-03-18 23:14:03 +01:00
|
|
|
public:
|
2014-01-14 05:05:43 +01:00
|
|
|
explicit SendCoinsRecipient() : amount(0), nVersion(SendCoinsRecipient::CURRENT_VERSION) { }
|
2014-04-23 00:46:19 +02:00
|
|
|
explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message):
|
2014-01-14 05:05:43 +01:00
|
|
|
address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
|
2013-07-22 08:50:39 +02:00
|
|
|
|
2013-10-24 16:02:39 +02:00
|
|
|
// 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!
|
2011-07-16 19:01:05 +02:00
|
|
|
QString address;
|
|
|
|
QString label;
|
2014-04-23 00:46:19 +02:00
|
|
|
CAmount amount;
|
2013-10-27 21:52:01 +01:00
|
|
|
// If from a payment request, this is used for storing the memo
|
2013-10-18 13:44:27 +02:00
|
|
|
QString message;
|
2013-07-22 08:50:39 +02:00
|
|
|
|
|
|
|
// If from a payment request, paymentRequest.IsInitialized() will be true
|
|
|
|
PaymentRequestPlus paymentRequest;
|
2013-10-24 16:02:39 +02:00
|
|
|
// Empty if no authentication or invalid signature/cert/etc.
|
|
|
|
QString authenticatedMerchant;
|
2014-01-14 05:05:43 +01:00
|
|
|
|
2014-01-22 09:46:15 +01:00
|
|
|
static const int CURRENT_VERSION = 1;
|
2014-01-14 05:05:43 +01:00
|
|
|
int nVersion;
|
|
|
|
|
2014-09-02 09:58:09 +02:00
|
|
|
ADD_SERIALIZE_METHODS;
|
overhaul serialization code
The implementation of each class' serialization/deserialization is no longer
passed within a macro. The implementation now lies within a template of form:
template <typename T, typename Stream, typename Operation>
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) {
size_t nSerSize = 0;
/* CODE */
return nSerSize;
}
In cases when codepath should depend on whether or not we are just deserializing
(old fGetSize, fWrite, fRead flags) an additional clause can be used:
bool fRead = boost::is_same<Operation, CSerActionUnserialize>();
The IMPLEMENT_SERIALIZE macro will now be a freestanding clause added within
class' body (similiar to Qt's Q_OBJECT) to implement GetSerializeSize,
Serialize and Unserialize. These are now wrappers around
the "SerializationOp" template.
2014-08-20 08:42:31 +02:00
|
|
|
|
2014-08-20 22:44:38 +02:00
|
|
|
template <typename Stream, typename Operation>
|
2014-08-21 00:49:32 +02:00
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
2014-09-01 21:36:46 +02:00
|
|
|
std::string sAddress = address.toStdString();
|
|
|
|
std::string sLabel = label.toStdString();
|
|
|
|
std::string sMessage = message.toStdString();
|
2014-01-14 05:05:43 +01:00
|
|
|
std::string sPaymentRequest;
|
2014-09-01 21:36:46 +02:00
|
|
|
if (!ser_action.ForRead() && paymentRequest.IsInitialized())
|
|
|
|
paymentRequest.SerializeToString(&sPaymentRequest);
|
|
|
|
std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
|
2014-01-14 05:05:43 +01:00
|
|
|
|
2014-09-01 21:36:46 +02:00
|
|
|
READWRITE(this->nVersion);
|
|
|
|
nVersion = this->nVersion;
|
2014-01-14 05:05:43 +01:00
|
|
|
READWRITE(sAddress);
|
|
|
|
READWRITE(sLabel);
|
2014-08-20 22:44:38 +02:00
|
|
|
READWRITE(amount);
|
2014-01-14 05:05:43 +01:00
|
|
|
READWRITE(sMessage);
|
|
|
|
READWRITE(sPaymentRequest);
|
|
|
|
READWRITE(sAuthenticatedMerchant);
|
|
|
|
|
2014-09-01 21:36:46 +02:00
|
|
|
if (ser_action.ForRead())
|
2014-01-14 05:05:43 +01:00
|
|
|
{
|
2014-09-01 21:36:46 +02:00
|
|
|
address = QString::fromStdString(sAddress);
|
|
|
|
label = QString::fromStdString(sLabel);
|
|
|
|
message = QString::fromStdString(sMessage);
|
2014-01-14 05:05:43 +01:00
|
|
|
if (!sPaymentRequest.empty())
|
2014-09-01 21:36:46 +02:00
|
|
|
paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
|
|
|
|
authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
|
2014-01-14 05:05:43 +01:00
|
|
|
}
|
overhaul serialization code
The implementation of each class' serialization/deserialization is no longer
passed within a macro. The implementation now lies within a template of form:
template <typename T, typename Stream, typename Operation>
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) {
size_t nSerSize = 0;
/* CODE */
return nSerSize;
}
In cases when codepath should depend on whether or not we are just deserializing
(old fGetSize, fWrite, fRead flags) an additional clause can be used:
bool fRead = boost::is_same<Operation, CSerActionUnserialize>();
The IMPLEMENT_SERIALIZE macro will now be a freestanding clause added within
class' body (similiar to Qt's Q_OBJECT) to implement GetSerializeSize,
Serialize and Unserialize. These are now wrappers around
the "SerializationOp" template.
2014-08-20 08:42:31 +02:00
|
|
|
}
|
2011-07-16 19:01:05 +02:00
|
|
|
};
|
|
|
|
|
2011-11-13 13:19:52 +01:00
|
|
|
/** Interface to Bitcoin wallet from Qt view code. */
|
2011-06-30 18:05:29 +02:00
|
|
|
class WalletModel : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
2013-01-23 21:51:02 +01:00
|
|
|
|
2011-06-30 18:05:29 +02:00
|
|
|
public:
|
2011-07-29 14:36:35 +02:00
|
|
|
explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0);
|
2012-05-06 19:40:58 +02:00
|
|
|
~WalletModel();
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2011-08-31 16:08:31 +02:00
|
|
|
enum StatusCode // Returned by sendCoins
|
2011-06-30 18:05:29 +02:00
|
|
|
{
|
|
|
|
OK,
|
|
|
|
InvalidAmount,
|
|
|
|
InvalidAddress,
|
|
|
|
AmountExceedsBalance,
|
|
|
|
AmountWithFeeExceedsBalance,
|
2011-07-16 19:01:05 +02:00
|
|
|
DuplicateAddress,
|
2011-08-31 16:08:31 +02:00
|
|
|
TransactionCreationFailed, // Error returned when wallet is still locked
|
2013-12-16 09:46:55 +01:00
|
|
|
TransactionCommitFailed
|
2011-06-30 18:05:29 +02:00
|
|
|
};
|
|
|
|
|
2011-08-23 20:08:42 +02:00
|
|
|
enum EncryptionStatus
|
|
|
|
{
|
|
|
|
Unencrypted, // !wallet->IsCrypted()
|
|
|
|
Locked, // wallet->IsCrypted() && wallet->IsLocked()
|
|
|
|
Unlocked // wallet->IsCrypted() && !wallet->IsLocked()
|
|
|
|
};
|
|
|
|
|
2011-06-30 18:05:29 +02:00
|
|
|
OptionsModel *getOptionsModel();
|
|
|
|
AddressTableModel *getAddressTableModel();
|
|
|
|
TransactionTableModel *getTransactionTableModel();
|
2013-11-05 18:03:05 +01:00
|
|
|
RecentRequestsTableModel *getRecentRequestsTableModel();
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2014-04-23 00:46:19 +02:00
|
|
|
CAmount getBalance(const CCoinControl *coinControl = NULL) const;
|
|
|
|
CAmount getUnconfirmedBalance() const;
|
|
|
|
CAmount getImmatureBalance() const;
|
2014-07-26 21:05:11 +02:00
|
|
|
bool haveWatchOnly() const;
|
2014-04-23 00:46:19 +02:00
|
|
|
CAmount getWatchBalance() const;
|
|
|
|
CAmount getWatchUnconfirmedBalance() const;
|
|
|
|
CAmount getWatchImmatureBalance() const;
|
2011-08-23 20:08:42 +02:00
|
|
|
EncryptionStatus getEncryptionStatus() const;
|
|
|
|
|
2011-07-16 19:01:05 +02:00
|
|
|
// Check address for validity
|
|
|
|
bool validateAddress(const QString &address);
|
|
|
|
|
2011-08-08 17:38:17 +02:00
|
|
|
// Return status record for SendCoins, contains error id + information
|
2011-07-16 19:01:05 +02:00
|
|
|
struct SendCoinsReturn
|
|
|
|
{
|
2013-12-16 09:46:55 +01:00
|
|
|
SendCoinsReturn(StatusCode status = OK):
|
2013-08-30 20:04:48 +02:00
|
|
|
status(status) {}
|
2011-07-16 19:01:05 +02:00
|
|
|
StatusCode status;
|
|
|
|
};
|
|
|
|
|
2013-08-30 20:04:48 +02:00
|
|
|
// prepare transaction for getting txfee before sending coins
|
2013-11-16 17:37:31 +01:00
|
|
|
SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl = NULL);
|
2013-08-30 20:04:48 +02:00
|
|
|
|
2011-08-08 17:38:17 +02:00
|
|
|
// Send coins to a list of recipients
|
2013-08-30 20:04:48 +02:00
|
|
|
SendCoinsReturn sendCoins(WalletModelTransaction &transaction);
|
2011-08-24 22:07:26 +02:00
|
|
|
|
|
|
|
// Wallet encryption
|
2011-11-26 07:02:04 +01:00
|
|
|
bool setWalletEncrypted(bool encrypted, const SecureString &passphrase);
|
2011-08-24 22:07:26 +02:00
|
|
|
// Passphrase only needed when unlocking
|
2011-11-26 07:02:04 +01:00
|
|
|
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
|
|
|
|
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
|
2012-02-14 13:14:43 +01:00
|
|
|
// Wallet backup
|
|
|
|
bool backupWallet(const QString &filename);
|
2011-08-24 22:07:26 +02:00
|
|
|
|
|
|
|
// RAI object for unlocking wallet, returned by requestUnlock()
|
|
|
|
class UnlockContext
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
UnlockContext(WalletModel *wallet, bool valid, bool relock);
|
|
|
|
~UnlockContext();
|
|
|
|
|
|
|
|
bool isValid() const { return valid; }
|
|
|
|
|
2011-08-31 16:08:31 +02:00
|
|
|
// Copy operator and constructor transfer the context
|
|
|
|
UnlockContext(const UnlockContext& obj) { CopyFrom(obj); }
|
|
|
|
UnlockContext& operator=(const UnlockContext& rhs) { CopyFrom(rhs); return *this; }
|
2011-08-24 22:07:26 +02:00
|
|
|
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();
|
|
|
|
|
2013-08-12 17:03:03 +02:00
|
|
|
bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
|
|
|
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
|
2014-02-15 22:38:28 +01:00
|
|
|
bool isSpent(const COutPoint& outpoint) const;
|
2013-08-12 17:03:03 +02:00
|
|
|
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);
|
|
|
|
|
2014-01-14 05:05:43 +01:00
|
|
|
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
|
|
|
|
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
|
|
|
|
|
2011-06-30 18:05:29 +02:00
|
|
|
private:
|
|
|
|
CWallet *wallet;
|
2014-07-26 21:05:11 +02:00
|
|
|
bool fHaveWatchOnly;
|
2014-08-17 02:34:42 +02:00
|
|
|
bool fForceCheckBalanceChanged;
|
2011-06-30 18:05:29 +02:00
|
|
|
|
|
|
|
// Wallet has an options model for wallet-specific options
|
|
|
|
// (transaction fee, for example)
|
|
|
|
OptionsModel *optionsModel;
|
|
|
|
|
|
|
|
AddressTableModel *addressTableModel;
|
|
|
|
TransactionTableModel *transactionTableModel;
|
2013-11-05 18:03:05 +01:00
|
|
|
RecentRequestsTableModel *recentRequestsTableModel;
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2011-08-31 16:08:31 +02:00
|
|
|
// Cache some values to be able to detect changes
|
2014-04-23 00:46:19 +02:00
|
|
|
CAmount cachedBalance;
|
|
|
|
CAmount cachedUnconfirmedBalance;
|
|
|
|
CAmount cachedImmatureBalance;
|
|
|
|
CAmount cachedWatchOnlyBalance;
|
|
|
|
CAmount cachedWatchUnconfBalance;
|
|
|
|
CAmount cachedWatchImmatureBalance;
|
2011-08-23 20:08:42 +02:00
|
|
|
EncryptionStatus cachedEncryptionStatus;
|
2012-07-05 17:43:28 +02:00
|
|
|
int cachedNumBlocks;
|
|
|
|
|
|
|
|
QTimer *pollTimer;
|
2011-07-17 14:06:43 +02:00
|
|
|
|
2012-05-06 19:40:58 +02:00
|
|
|
void subscribeToCoreSignals();
|
|
|
|
void unsubscribeFromCoreSignals();
|
2012-07-05 17:43:28 +02:00
|
|
|
void checkBalanceChanged();
|
|
|
|
|
2011-06-30 18:05:29 +02:00
|
|
|
signals:
|
2011-08-31 16:08:31 +02:00
|
|
|
// Signal that balance in wallet changed
|
2014-04-23 00:46:19 +02:00
|
|
|
void balanceChanged(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance,
|
|
|
|
const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance);
|
2011-08-31 16:08:31 +02:00
|
|
|
|
|
|
|
// Encryption status of wallet changed
|
2011-08-23 20:08:42 +02:00
|
|
|
void encryptionStatusChanged(int status);
|
2011-08-31 16:08:31 +02:00
|
|
|
|
|
|
|
// 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.
|
2011-08-24 22:07:26 +02:00
|
|
|
void requireUnlock();
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2013-10-24 16:02:39 +02:00
|
|
|
// Fired when a message should be reported to the user
|
2012-12-03 13:24:42 +01:00
|
|
|
void message(const QString &title, const QString &message, unsigned int style);
|
2011-06-30 18:05:29 +02:00
|
|
|
|
2013-07-22 08:50:39 +02:00
|
|
|
// Coins sent: from wallet, to recipient, in (serialized) transaction:
|
|
|
|
void coinsSent(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction);
|
|
|
|
|
2014-03-19 00:26:14 +01:00
|
|
|
// Show progress dialog e.g. for rescan
|
|
|
|
void showProgress(const QString &title, int nProgress);
|
|
|
|
|
2014-07-26 21:05:11 +02:00
|
|
|
// Watch-only address added
|
|
|
|
void notifyWatchonlyChanged(bool fHaveWatchonly);
|
|
|
|
|
2011-06-30 18:05:29 +02:00
|
|
|
public slots:
|
2012-05-05 16:07:14 +02:00
|
|
|
/* Wallet status might have changed */
|
|
|
|
void updateStatus();
|
|
|
|
/* New transaction, or transaction changed status */
|
2014-10-28 19:52:21 +01:00
|
|
|
void updateTransaction();
|
2012-05-05 16:07:14 +02:00
|
|
|
/* New, updated or removed address book entry */
|
2013-08-29 16:19:43 +02:00
|
|
|
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
|
2014-08-28 23:20:46 +02:00
|
|
|
/* Watch-only added */
|
2014-07-26 21:05:11 +02:00
|
|
|
void updateWatchOnlyFlag(bool fHaveWatchonly);
|
2012-07-05 17:43:28 +02:00
|
|
|
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
|
|
|
|
void pollBalanceChanged();
|
2011-06-30 18:05:29 +02:00
|
|
|
};
|
|
|
|
|
2014-11-03 16:16:40 +01:00
|
|
|
#endif // BITCOIN_QT_WALLETMODEL_H
|