Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ QT_FORMS_UI = \
qt/forms/intro.ui \
qt/forms/masternodelist.ui \
qt/forms/multisenddialog.ui \
qt/forms/multisigdialog.ui\
qt/forms/openuridialog.ui \
qt/forms/optionsdialog.ui \
qt/forms/overviewpage.ui \
Expand Down Expand Up @@ -76,6 +77,7 @@ QT_MOC_CPP = \
qt/moc_macnotificationhandler.cpp \
qt/moc_masternodelist.cpp \
qt/moc_multisenddialog.cpp \
qt/moc_multisigdialog.cpp\
qt/moc_notificator.cpp \
qt/moc_openuridialog.cpp \
qt/moc_optionsdialog.cpp \
Expand Down Expand Up @@ -149,6 +151,7 @@ BITCOIN_QT_H = \
qt/macnotificationhandler.h \
qt/masternodelist.h \
qt/multisenddialog.h \
qt/multisigdialog.h\
qt/networkstyle.h \
qt/notificator.h \
qt/openuridialog.h \
Expand Down Expand Up @@ -282,6 +285,7 @@ BITCOIN_QT_CPP += \
qt/editaddressdialog.cpp \
qt/masternodelist.cpp \
qt/multisenddialog.cpp \
qt/multisigdialog.cpp\
qt/openuridialog.cpp \
qt/overviewpage.cpp \
qt/paymentrequestplus.cpp \
Expand Down
13 changes: 12 additions & 1 deletion src/coincontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class CCoinControl
useSwiftTX = false;
useObfuScation = false;
fAllowOtherInputs = false;
fAllowWatchOnly = false;
fAllowWatchOnly = true;
nMinimumTotalFee = 0;
fSplitBlock = false;
nSplitBlock = 1;
Expand Down Expand Up @@ -75,6 +75,17 @@ class CCoinControl
vOutpoints.assign(setSelected.begin(), setSelected.end());
}

unsigned int QuantitySelected()
{
return setSelected.size();
}

void SetSelection(std::set<COutPoint> setSelected)
{
this->setSelected.clear();
this->setSelected = setSelected;
}

private:
std::set<COutPoint> setSelected;
};
Expand Down
26 changes: 26 additions & 0 deletions src/keystore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,29 @@ bool CBasicKeyStore::HaveWatchOnly() const
LOCK(cs_KeyStore);
return (!setWatchOnly.empty());
}

bool CBasicKeyStore::AddMultiSig(const CScript& dest)
{
LOCK(cs_KeyStore);
setMultiSig.insert(dest);
return true;
}

bool CBasicKeyStore::RemoveMultiSig(const CScript& dest)
{
LOCK(cs_KeyStore);
setMultiSig.erase(dest);
return true;
}

bool CBasicKeyStore::HaveMultiSig(const CScript& dest) const
{
LOCK(cs_KeyStore);
return setMultiSig.count(dest) > 0;
}

bool CBasicKeyStore::HaveMultiSig() const
{
LOCK(cs_KeyStore);
return (!setMultiSig.empty());
}
13 changes: 13 additions & 0 deletions src/keystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,18 @@ class CKeyStore
virtual bool RemoveWatchOnly(const CScript& dest) = 0;
virtual bool HaveWatchOnly(const CScript& dest) const = 0;
virtual bool HaveWatchOnly() const = 0;

//! Support for MultiSig addresses
virtual bool AddMultiSig(const CScript& dest) = 0;
virtual bool RemoveMultiSig(const CScript& dest) = 0;
virtual bool HaveMultiSig(const CScript& dest) const = 0;
virtual bool HaveMultiSig() const = 0;
};

typedef std::map<CKeyID, CKey> KeyMap;
typedef std::map<CScriptID, CScript> ScriptMap;
typedef std::set<CScript> WatchOnlySet;
typedef std::set<CScript> MultiSigScriptSet;

/** Basic key store, that keeps keys in an address->secret map */
class CBasicKeyStore : public CKeyStore
Expand All @@ -58,6 +65,7 @@ class CBasicKeyStore : public CKeyStore
KeyMap mapKeys;
ScriptMap mapScripts;
WatchOnlySet setWatchOnly;
MultiSigScriptSet setMultiSig;

public:
bool AddKeyPubKey(const CKey& key, const CPubKey& pubkey);
Expand Down Expand Up @@ -102,6 +110,11 @@ class CBasicKeyStore : public CKeyStore
virtual bool RemoveWatchOnly(const CScript& dest);
virtual bool HaveWatchOnly(const CScript& dest) const;
virtual bool HaveWatchOnly() const;

virtual bool AddMultiSig(const CScript& dest);
virtual bool RemoveMultiSig(const CScript& dest);
virtual bool HaveMultiSig(const CScript& dest) const;
virtual bool HaveMultiSig() const;
};

typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
Expand Down
35 changes: 35 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle* networkStyle, QWidget* parent) : QMai
signMessageAction(0),
verifyMessageAction(0),
bip38ToolAction(0),
multisigCreateAction(0),
multisigSpendAction(0),
multisigSignAction(0),
aboutAction(0),
receiveCoinsAction(0),
privacyAction(0),
Expand Down Expand Up @@ -433,6 +436,13 @@ void BitcoinGUI::createActions(const NetworkStyle* networkStyle)
usedReceivingAddressesAction = new QAction(QIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));

multisigCreateAction = new QAction(QIcon(":/icons/address-book"), tr("&Multisignature creation..."), this);
multisigCreateAction->setStatusTip(tr("Create a new multisignature address and add it to this wallet"));
multisigSpendAction = new QAction(QIcon(":/icons/send"), tr("&Multisignature spending..."), this);
multisigSpendAction->setStatusTip(tr("Spend from a multisignature address"));
multisigSignAction = new QAction(QIcon(":/icons/editpaste"), tr("&Multisignature signing..."), this);
multisigSignAction->setStatusTip(tr("Sign with a multisignature address"));

openAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_FileIcon), tr("Open &URI..."), this);
openAction->setStatusTip(tr("Open a PIVX: URI or payment request"));
openBlockExplorerAction = new QAction(QIcon(":/icons/explorer"), tr("&Blockchain explorer"), this);
Expand Down Expand Up @@ -462,6 +472,9 @@ void BitcoinGUI::createActions(const NetworkStyle* networkStyle)
connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
connect(multiSendAction, SIGNAL(triggered()), this, SLOT(gotoMultiSendDialog()));
connect(multisigCreateAction, SIGNAL(triggered()), this, SLOT(gotoMultisigCreate()));
connect(multisigSpendAction, SIGNAL(triggered()), this, SLOT(gotoMultisigSpend()));
connect(multisigSignAction, SIGNAL(triggered()), this, SLOT(gotoMultisigSign()));
}
#endif // ENABLE_WALLET
}
Expand All @@ -487,6 +500,10 @@ void BitcoinGUI::createMenuBar()
file->addAction(usedSendingAddressesAction);
file->addAction(usedReceivingAddressesAction);
file->addSeparator();
file->addAction(multisigCreateAction);
file->addAction(multisigSpendAction);
file->addAction(multisigSignAction);
file->addSeparator();
}
file->addAction(quitAction);

Expand Down Expand Up @@ -634,6 +651,9 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
changePassphraseAction->setEnabled(enabled);
signMessageAction->setEnabled(enabled);
verifyMessageAction->setEnabled(enabled);
multisigCreateAction->setEnabled(enabled);
multisigSpendAction->setEnabled(enabled);
multisigSignAction->setEnabled(enabled);
bip38ToolAction->setEnabled(enabled);
usedSendingAddressesAction->setEnabled(enabled);
usedReceivingAddressesAction->setEnabled(enabled);
Expand Down Expand Up @@ -795,6 +815,21 @@ void BitcoinGUI::gotoVerifyMessageTab(QString addr)
if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
}

void BitcoinGUI::gotoMultisigCreate()
{
if(walletFrame) walletFrame->gotoMultisigDialog(0);
}

void BitcoinGUI::gotoMultisigSpend()
{
if(walletFrame) walletFrame->gotoMultisigDialog(1);
}

void BitcoinGUI::gotoMultisigSign()
{
if(walletFrame) walletFrame->gotoMultisigDialog(2);
}

void BitcoinGUI::gotoBip38Tool()
{
if (walletFrame) walletFrame->gotoBip38Tool();
Expand Down
8 changes: 7 additions & 1 deletion src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class BitcoinGUI : public QMainWindow
QAction* signMessageAction;
QAction* verifyMessageAction;
QAction* bip38ToolAction;
QAction* multisigCreateAction;
QAction* multisigSpendAction;
QAction* multisigSignAction;
QAction* aboutAction;
QAction* receiveCoinsAction;
QAction* privacyAction;
Expand Down Expand Up @@ -215,7 +218,10 @@ private slots:
void gotoVerifyMessageTab(QString addr = "");
/** Show MultiSend Dialog */
void gotoMultiSendDialog();

/** Show MultiSig Dialog */
void gotoMultisigCreate();
void gotoMultisigSpend();
void gotoMultisigSign();
/** Show BIP 38 tool - default to Encryption tab */
void gotoBip38Tool();

Expand Down
74 changes: 70 additions & 4 deletions src/qt/coincontroldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "main.h"
#include "obfuscation.h"
#include "wallet.h"
#include "multisigdialog.h"

#include <boost/assign/list_of.hpp> // for 'map_list_of()'

Expand All @@ -37,11 +38,12 @@ QList<CAmount> CoinControlDialog::payAmounts;
int CoinControlDialog::nSplitBlockDummy;
CCoinControl* CoinControlDialog::coinControl = new CCoinControl();

CoinControlDialog::CoinControlDialog(QWidget* parent) : QDialog(parent),
CoinControlDialog::CoinControlDialog(QWidget* parent, bool fMultisigEnabled) : QDialog(parent),
ui(new Ui::CoinControlDialog),
model(0)
{
ui->setupUi(this);
this->fMultisigEnabled = fMultisigEnabled;

/* Open CSS when configured */
this->setStyleSheet(GUIUtil::loadStyleSheet());
Expand Down Expand Up @@ -171,6 +173,7 @@ void CoinControlDialog::setModel(WalletModel* model)
updateView();
updateLabelLocked();
CoinControlDialog::updateLabels(model, this);
updateDialogLabels();
}
}

Expand Down Expand Up @@ -208,6 +211,7 @@ void CoinControlDialog::buttonSelectAllClicked()
if (state == Qt::Unchecked)
coinControl->UnSelectAll(); // just to be sure
CoinControlDialog::updateLabels(model, this);
updateDialogLabels();
}

// Toggle lock state
Expand All @@ -219,6 +223,10 @@ void CoinControlDialog::buttonToggleLockClicked()
ui->treeWidget->setEnabled(false);
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) {
item = ui->treeWidget->topLevelItem(i);

if (item->text(COLUMN_TYPE) == "MultiSig")
continue;

COutPoint outpt(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt());
if (model->isLockedCoin(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) {
model->unlockCoin(outpt);
Expand All @@ -233,6 +241,7 @@ void CoinControlDialog::buttonToggleLockClicked()
}
ui->treeWidget->setEnabled(true);
CoinControlDialog::updateLabels(model, this);
updateDialogLabels();
} else {
QMessageBox msgBox;
msgBox.setObjectName("lockMessageBox");
Expand Down Expand Up @@ -431,8 +440,10 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
coinControl->Select(outpt);

// selection changed -> update labels
if (ui->treeWidget->isEnabled()) // do not update on every click for (un)select all
if (ui->treeWidget->isEnabled()){ // do not update on every click for (un)select all
CoinControlDialog::updateLabels(model, this);
updateDialogLabels();
}
}
// todo: this is a temporary qt5 fix: when clicking a parent node in tree mode, the parent node
// including all childs are partially selected. But the parent node should be fully selected
Expand Down Expand Up @@ -486,6 +497,42 @@ void CoinControlDialog::updateLabelLocked()
ui->labelLocked->setVisible(false);
}

void CoinControlDialog::updateDialogLabels()
{

if (this->parentWidget() == nullptr) {
CoinControlDialog::updateLabels(model, this);
return;
}

vector<COutPoint> vCoinControl;
vector<COutput> vOutputs;
coinControl->ListSelected(vCoinControl);
model->getOutputs(vCoinControl, vOutputs);

CAmount nAmount = 0;
unsigned int nQuantity = 0;
for (const COutput& out : vOutputs) {
// unselect already spent, very unlikely scenario, this could happen
// when selected are spent elsewhere, like rpc or another computer
uint256 txhash = out.tx->GetHash();
COutPoint outpt(txhash, out.i);
if(model->isSpent(outpt)) {
coinControl->UnSelect(outpt);
continue;
}

// Quantity
nQuantity++;

// Amount
nAmount += out.tx->vout[out.i].nValue;
}
MultisigDialog* multisigDialog = (MultisigDialog*)this->parentWidget();

multisigDialog->updateCoinControl(nAmount, nQuantity);
}

void CoinControlDialog::updateLabels(WalletModel* model, QDialog* dialog)
{
if (!model)
Expand Down Expand Up @@ -700,7 +747,7 @@ void CoinControlDialog::updateView()
int nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget);

map<QString, vector<COutput> > mapCoins;
map<QString, vector<COutput>> mapCoins;
model->listCoins(mapCoins);

BOOST_FOREACH (PAIRTYPE(QString, vector<COutput>) coins, mapCoins) {
Expand Down Expand Up @@ -731,7 +778,12 @@ void CoinControlDialog::updateView()
double dPrioritySum = 0;
int nChildren = 0;
int nInputSum = 0;
BOOST_FOREACH (const COutput& out, coins.second) {
for(const COutput& out: coins.second) {
isminetype mine = pwalletMain->IsMine(out.tx->vout[out.i]);
bool fMultiSigUTXO = (mine & ISMINE_MULTISIG);
// when multisig is enabled, it will only display outputs from multisig addresses
if (fMultisigEnabled && !fMultiSigUTXO)
continue;
int nInputSize = 0;
nSum += out.tx->vout[out.i].nValue;
nChildren++;
Expand All @@ -744,6 +796,20 @@ void CoinControlDialog::updateView()
itemOutput->setFlags(flgCheckbox);
itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);

//MultiSig
if (fMultiSigUTXO) {
itemOutput->setText(COLUMN_TYPE, "MultiSig");

if (!fMultisigEnabled) {
COutPoint outpt(out.tx->GetHash(), out.i);
coinControl->UnSelect(outpt); // just to be sure
itemOutput->setDisabled(true);
itemOutput->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed"));
}
} else {
itemOutput->setText(COLUMN_TYPE, "Personal");
}

// address
CTxDestination outputAddress;
QString sAddress = "";
Expand Down
Loading