diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index de991126f62c..0f90823a1b4c 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -345,7 +345,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con else if(type == Receive) { // Generate a new address to associate with given label - WalletModel::UnlockContext ctx(walletModel->requestUnlock()); + WalletModel::UnlockContext ctx(walletModel->requestUnlock(true)); if(!ctx.isValid()) { // Unlock wallet failed or was cancelled diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index e17ba810a0c0..9abffcd673cd 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -25,7 +25,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : ui->passEdit2->installEventFilter(this); ui->passEdit3->installEventFilter(this); - switch(mode) + switch(mode) { case Encrypt: // Ask passphrase x2 ui->passLabel1->hide(); @@ -33,6 +33,9 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of 10 or more random characters, or eight or more words.")); setWindowTitle(tr("Encrypt wallet")); break; + case UnlockAnonymize: + ui->anonymizationCheckBox->setChecked(true); + ui->anonymizationCheckBox->show(); case Unlock: // Ask passphrase ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet.")); ui->passLabel2->hide(); @@ -73,6 +76,7 @@ AskPassphraseDialog::~AskPassphraseDialog() void AskPassphraseDialog::setModel(WalletModel *model) { this->model = model; + ui->anonymizationCheckBox->setChecked(model->isAnonymizeOnlyUnlocked()); } void AskPassphraseDialog::accept() @@ -138,8 +142,9 @@ void AskPassphraseDialog::accept() QDialog::reject(); // Cancelled } } break; + case UnlockAnonymize: case Unlock: - if(!model->setWalletLocked(false, oldpass)) + if(!model->setWalletLocked(false, oldpass, ui->anonymizationCheckBox->isChecked())) { QMessageBox::critical(this, tr("Wallet unlock failed"), tr("The passphrase entered for the wallet decryption was incorrect.")); @@ -193,6 +198,7 @@ void AskPassphraseDialog::textChanged() case Encrypt: // New passphrase x2 acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); break; + case UnlockAnonymize: // Old passphrase x1 case Unlock: // Old passphrase x1 case Decrypt: acceptable = !ui->passEdit1->text().isEmpty(); diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 9df002da2cea..290067de61cf 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -17,6 +17,7 @@ class AskPassphraseDialog : public QDialog public: enum Mode { Encrypt, /**< Ask passphrase twice and encrypt */ + UnlockAnonymize, /**< Ask passphrase and unlock only for anonymization */ Unlock, /**< Ask passphrase and unlock */ ChangePass, /**< Ask old passphrase + new passphrase twice */ Decrypt /**< Ask passphrase and decrypt wallet */ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b14fa017fa79..59557261858e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -240,6 +240,10 @@ void BitcoinGUI::createActions() backupWalletAction->setStatusTip(tr("Backup wallet to another location")); changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this); changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption")); + unlockWalletAction = new QAction(tr("&Unlock Wallet..."), this); + unlockWalletAction->setToolTip(tr("Unlock wallet")); + lockWalletAction = new QAction(tr("&Lock Wallet"), this); + lockWalletAction->setToolTip(tr("Lock wallet")); signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this); signMessageAction->setStatusTip(tr("Sign messages with your DarkCoin addresses to prove you own them")); verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); @@ -256,6 +260,8 @@ void BitcoinGUI::createActions() connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool))); connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet())); connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase())); + connect(unlockWalletAction, SIGNAL(triggered()), walletFrame, SLOT(unlockWallet())); + connect(lockWalletAction, SIGNAL(triggered()), walletFrame, SLOT(lockWallet())); connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab())); connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab())); } @@ -281,6 +287,8 @@ void BitcoinGUI::createMenuBar() QMenu *settings = appMenuBar->addMenu(tr("&Settings")); settings->addAction(encryptWalletAction); settings->addAction(changePassphraseAction); + settings->addAction(unlockWalletAction); + settings->addAction(lockWalletAction); settings->addSeparator(); settings->addAction(optionsAction); @@ -810,6 +818,8 @@ void BitcoinGUI::setEncryptionStatus(int status) labelEncryptionIcon->hide(); encryptWalletAction->setChecked(false); changePassphraseAction->setEnabled(false); + unlockWalletAction->setVisible(false); + lockWalletAction->setVisible(false); encryptWalletAction->setEnabled(true); break; case WalletModel::Unlocked: @@ -818,6 +828,18 @@ void BitcoinGUI::setEncryptionStatus(int status) labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(false); + lockWalletAction->setVisible(true); + encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + break; + case WalletModel::UnlockedForAnonymizationOnly: + labelEncryptionIcon->show(); + labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked for anonimization only")); + encryptWalletAction->setChecked(true); + changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(true); + lockWalletAction->setVisible(true); encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported break; case WalletModel::Locked: @@ -826,6 +848,8 @@ void BitcoinGUI::setEncryptionStatus(int status) labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently locked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(true); + lockWalletAction->setVisible(false); encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported break; } diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index ab89410155b1..94103b94e18b 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -101,6 +101,8 @@ class BitcoinGUI : public QMainWindow QAction *encryptWalletAction; QAction *backupWalletAction; QAction *changePassphraseAction; + QAction *unlockWalletAction; + QAction *lockWalletAction; QAction *aboutQtAction; QAction *openRPCConsoleAction; diff --git a/src/qt/forms/askpassphrasedialog.ui b/src/qt/forms/askpassphrasedialog.ui index 25169042a102..72da2a4e2e46 100644 --- a/src/qt/forms/askpassphrasedialog.ui +++ b/src/qt/forms/askpassphrasedialog.ui @@ -99,6 +99,22 @@ + + + + true + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + For anonymization only + + + false + + + diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 38fdb789300c..277e5a273c14 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -183,7 +183,7 @@ void OptionsDialog::setSaveButtonState(bool fState) ui->okButton->setEnabled(fState); } -void OptionsDialog::on_resetButton_clicked() +/*void OptionsDialog::on_resetButton_clicked() { if(model) { @@ -197,18 +197,18 @@ void OptionsDialog::on_resetButton_clicked() disableApplyButton(); - /* disable restart warning messages display */ + // disable restart warning messages display fRestartWarningDisplayed_Lang = fRestartWarningDisplayed_Proxy = true; - /* reset all options and save the default values (QSettings) */ + // reset all options and save the default values (QSettings) model->Reset(); mapper->toFirst(); mapper->submit(); - /* re-enable restart warning messages display */ + // re-enable restart warning messages display fRestartWarningDisplayed_Lang = fRestartWarningDisplayed_Proxy = false; } -} +}*/ void OptionsDialog::on_okButton_clicked() { diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index d64ed0b57fe1..1c278030f57f 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -36,7 +36,7 @@ private slots: void disableSaveButtons(); /* set apply button and OK button state (enabled / disabled) */ void setSaveButtonState(bool fState); - void on_resetButton_clicked(); +// void on_resetButton_clicked(); void on_okButton_clicked(); void on_cancelButton_clicked(); void on_applyButton_clicked(); diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 020a3ba89305..2b0d364bb7e2 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -285,6 +285,7 @@ void OverviewPage::darkSendStatus() ui->darksendEnabled->setText("Disabled"); ui->darksendStatus->setText(""); + ui->toggleDarksend->setText("Start Darksend Mixing"); } return; @@ -298,17 +299,21 @@ void OverviewPage::darkSendStatus() if (pwalletMain->GetBalance() - pwalletMain->GetAnonymizedBalance() > 2*COIN){ if (walletModel->getEncryptionStatus() != WalletModel::Unencrypted){ - if((nAnonymizeDarkcoinAmount*COIN)-pwalletMain->GetAnonymizedBalance() > 1.1*COIN && walletModel->getEncryptionStatus() == WalletModel::Locked){ - WalletModel::UnlockContext ctx(walletModel->requestUnlock()); + if((nAnonymizeDarkcoinAmount*COIN)-pwalletMain->GetAnonymizedBalance() > 1.1*COIN && + walletModel->getEncryptionStatus() == WalletModel::Locked){ + + WalletModel::UnlockContext ctx(walletModel->requestUnlock(false)); if(!ctx.isValid()){ //unlock was cancelled fEnableDarksend = false; + darkSendPool.cachedNumBlocks = 0; LogPrintf("Wallet is locked and user declined to unlock. Disabling Darksend.\n"); } } if((nAnonymizeDarkcoinAmount*COIN)-pwalletMain->GetAnonymizedBalance() <= 1.1*COIN && - walletModel->getEncryptionStatus() == WalletModel::Unlocked && + walletModel->getEncryptionStatus() == WalletModel::Unlocked && darkSendPool.GetMyTransactionCount() == 0){ + LogPrintf("Darksend is complete, locking wallet.\n"); walletModel->Lock(); } @@ -413,4 +418,4 @@ void OverviewPage::toggleDarksend(){ darkSendPool.DoAutomaticDenominating(); } -} \ No newline at end of file +} diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 61e9f076af30..753d8d60f507 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -184,7 +184,7 @@ void SendCoinsDialog::on_sendButton_clicked() return; } - WalletModel::UnlockContext ctx(model->requestUnlock()); + WalletModel::UnlockContext ctx(model->requestUnlock(true)); if(!ctx.isValid()) { // Unlock wallet was cancelled @@ -235,6 +235,11 @@ void SendCoinsDialog::on_sendButton_clicked() tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."), QMessageBox::Ok, QMessageBox::Ok); break; + case WalletModel::AnonymizeOnlyUnlocked: + QMessageBox::warning(this, tr("Send Coins"), + tr("Error: The wallet was unlocked only to anonymize coins."), + QMessageBox::Ok, QMessageBox::Ok); + break; case WalletModel::Aborted: // User aborted, nothing to do break; case WalletModel::OK: diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 6e3b4eba07f6..1e33b97e49bd 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -122,7 +122,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() return; } - WalletModel::UnlockContext ctx(model->requestUnlock()); + WalletModel::UnlockContext ctx(model->requestUnlock(true)); if (!ctx.isValid()) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index dc074e8883f0..d0d707f37ea9 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -147,6 +147,13 @@ void WalletFrame::unlockWallet() walletView->unlockWallet(); } +void WalletFrame::lockWallet() +{ + WalletView *walletView = currentWalletView(); + if (walletView) + walletView->lockWallet(); +} + void WalletFrame::setEncryptionStatus() { WalletView *walletView = currentWalletView(); diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 74454b1a991c..5e9a67cbbca4 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -66,6 +66,8 @@ public slots: void changePassphrase(); /** Ask for passphrase to unlock wallet temporarily */ void unlockWallet(); + /** Lock wallet */ + void lockWallet(); /** Set the encryption status as shown in the UI. @param[in] status current encryption status diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 16ad9c342d45..3d91584c338a 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -157,6 +157,11 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListfWalletUnlockAnonymizeOnly) + { + return UnlockedForAnonymizationOnly; + } else { return Unlocked; @@ -310,17 +319,18 @@ bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphr } } -bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase) +bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase, bool anonymizeOnly) { if(locked) { // Lock - return false; //wallet->Lock(); + // return false; //wallet->Lock(); + return wallet->Lock(); } else { // Unlock - return wallet->Unlock(passPhrase); + return wallet->Unlock(passPhrase, anonymizeOnly); } } @@ -329,6 +339,11 @@ void WalletModel::Lock() wallet->Lock(); } +bool WalletModel::isAnonymizeOnlyUnlocked() +{ + return wallet->fWalletUnlockAnonymizeOnly; +} + bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass) { bool retval; @@ -396,9 +411,16 @@ void WalletModel::unsubscribeFromCoreSignals() } // WalletModel::UnlockContext implementation -WalletModel::UnlockContext WalletModel::requestUnlock() +WalletModel::UnlockContext WalletModel::requestUnlock(bool relock) { bool was_locked = getEncryptionStatus() == Locked; + + if (!was_locked && isAnonymizeOnlyUnlocked()) + { + setWalletLocked(true); + was_locked = getEncryptionStatus() == Locked; + } + if(was_locked) { // Request UI to unlock wallet @@ -407,7 +429,8 @@ WalletModel::UnlockContext WalletModel::requestUnlock() // If wallet is still locked, unlock was failed or cancelled, mark context as invalid bool valid = getEncryptionStatus() != Locked; - return UnlockContext(this, valid, was_locked); + return UnlockContext(this, valid, relock); +// return UnlockContext(this, valid, was_locked && !isAnonymizeOnlyUnlocked()); } WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock): diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index df8c6a11d5af..fa0d9d8494d8 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -51,14 +51,16 @@ class WalletModel : public QObject DuplicateAddress, TransactionCreationFailed, // Error returned when wallet is still locked TransactionCommitFailed, - Aborted + Aborted, + AnonymizeOnlyUnlocked }; enum EncryptionStatus { Unencrypted, // !wallet->IsCrypted() Locked, // wallet->IsCrypted() && wallet->IsLocked() - Unlocked // wallet->IsCrypted() && !wallet->IsLocked() + Unlocked, // wallet->IsCrypted() && !wallet->IsLocked() + UnlockedForAnonymizationOnly // wallet->IsCrypted() && !wallet->IsLocked() && wallet->fWalletUnlockAnonymizeOnly }; OptionsModel *getOptionsModel(); @@ -93,9 +95,11 @@ class WalletModel : public QObject // Wallet encryption bool setWalletEncrypted(bool encrypted, const SecureString &passphrase); // Passphrase only needed when unlocking - bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString()); + bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString(), bool anonymizeOnly = true); void Lock(); bool changePassphrase(const SecureString &oldPass, const SecureString &newPass); + // Is wallet unlocked for anonymization only? + bool isAnonymizeOnlyUnlocked(); // Wallet backup bool backupWallet(const QString &filename); @@ -119,7 +123,7 @@ class WalletModel : public QObject void CopyFrom(const UnlockContext& rhs); }; - UnlockContext requestUnlock(); + UnlockContext requestUnlock(bool relock); bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; void getOutputs(const std::vector& vOutpoints, std::vector& vOutputs); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index dd2034c34d28..618b917ec259 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -266,10 +266,18 @@ void WalletView::unlockWallet() if(!walletModel) return; // Unlock wallet when requested by wallet model - if (walletModel->getEncryptionStatus() == WalletModel::Locked) + if (walletModel->getEncryptionStatus() == WalletModel::Locked || walletModel->getEncryptionStatus() == WalletModel::UnlockedForAnonymizationOnly) { - AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this); + AskPassphraseDialog dlg(AskPassphraseDialog::UnlockAnonymize, this); dlg.setModel(walletModel); dlg.exec(); } } + +void WalletView::lockWallet() +{ + if(!walletModel) + return; + + walletModel->setWalletLocked(true); +} diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 6ad5180d567c..8604d2206b59 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -97,6 +97,8 @@ public slots: void changePassphrase(); /** Ask for passphrase to unlock wallet temporarily */ void unlockWallet(); + /** Lock wallet */ + void lockWallet(); void setEncryptionStatus(); diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 0fce39e66c80..9859258e1d24 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -51,6 +51,8 @@ Value importprivkey(const Array& params, bool fHelp) bool fGood = vchSecret.SetString(strSecret); if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + if (pwalletMain->fWalletUnlockAnonymizeOnly) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for anonymization only"); CKey key = vchSecret.GetKey(); CPubKey pubkey = key.GetPubKey(); @@ -84,6 +86,8 @@ Value dumpprivkey(const Array& params, bool fHelp) CBitcoinAddress address; if (!address.SetString(strAddress)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DarkCoin address"); + if (pwalletMain->fWalletUnlockAnonymizeOnly) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for anonymization only"); CKeyID keyID; if (!address.GetKeyID(keyID)) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 0b29635be8f3..a1ebcffa49f8 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -30,6 +30,8 @@ void EnsureWalletIsUnlocked() { if (pwalletMain->IsLocked()) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); + if (pwalletMain->fWalletUnlockAnonymizeOnly) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for anonymization only"); } void WalletTxToJSON(const CWalletTx& wtx, Object& entry) @@ -1350,16 +1352,17 @@ void ThreadCleanWalletPassphrase(void* parg) Value walletpassphrase(const Array& params, bool fHelp) { - if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2)) + if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 3)) throw runtime_error( - "walletpassphrase \n" - "Stores the wallet decryption key in memory for seconds."); + "walletpassphrase [anonymizenonly]\n" + "Stores the wallet decryption key in memory for seconds.\n" + "if [anonymizeonly] is true sending functions are disabled."); if (fHelp) return true; if (!pwalletMain->IsCrypted()) throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called."); - if (!pwalletMain->IsLocked()) + if (!pwalletMain->IsLocked() && !pwalletMain->fWalletUnlockAnonymizeOnly) throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked."); // Note that the walletpassphrase is stored in params[0] which is not mlock()ed @@ -1371,13 +1374,23 @@ Value walletpassphrase(const Array& params, bool fHelp) if (strWalletPass.length() > 0) { - if (!pwalletMain->Unlock(strWalletPass)) + bool anonymizeOnly; + if (params.size() == 3) + anonymizeOnly = params[2].get_bool(); + else + anonymizeOnly = false; + + if (!pwalletMain->IsLocked() && pwalletMain->fWalletUnlockAnonymizeOnly && anonymizeOnly) + throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked."); + + if (!pwalletMain->Unlock(strWalletPass, anonymizeOnly)) throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); } else throw runtime_error( - "walletpassphrase \n" - "Stores the wallet decryption key in memory for seconds."); + "walletpassphrase [anonymizeonly]\n" + "Stores the wallet decryption key in memory for seconds.\n" + "if [anonymizeonly] is true sending functions are disabled."); NewThread(ThreadTopUpKeyPool, NULL); int64* pnSleepTime = new int64(params[1].get_int64()); diff --git a/src/wallet.cpp b/src/wallet.cpp index 5a72eb19ab98..4f0eaa532d67 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -90,10 +90,14 @@ bool CWallet::AddCScript(const CScript& redeemScript) return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); } -bool CWallet::Unlock(const SecureString& strWalletPassphrase) +bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool anonymizeOnly) { + if (!IsLocked()) - return false; + { + fWalletUnlockAnonymizeOnly = anonymizeOnly; + return true; + } CCrypter crypter; CKeyingMaterial vMasterKey; @@ -107,7 +111,10 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase) if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) return false; if (CCryptoKeyStore::Unlock(vMasterKey)) + { + fWalletUnlockAnonymizeOnly = anonymizeOnly; return true; + } } } return false; @@ -1691,7 +1698,13 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, if (IsLocked()) { string strError = _("Error: Wallet locked, unable to create transaction!"); - LogPrintf("SendMoney() : %s", strError.c_str()); + LogPrintf("SendMoney() : %s\n", strError.c_str()); + return strError; + } + if (fWalletUnlockAnonymizeOnly) + { + string strError = _("Error: Wallet unlocked for anonymization only, unable to create transaction."); + LogPrintf("SendMoney() : %s\n", strError.c_str()); return strError; } diff --git a/src/wallet.h b/src/wallet.h index b14a5f48e288..46c7f99574d4 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -103,6 +103,7 @@ class CWallet : public CCryptoKeyStore mutable CCriticalSection cs_wallet; bool fFileBacked; + bool fWalletUnlockAnonymizeOnly; std::string strWalletFile; std::set setKeyPool; @@ -117,6 +118,7 @@ class CWallet : public CCryptoKeyStore nWalletVersion = FEATURE_BASE; nWalletMaxVersion = FEATURE_BASE; fFileBacked = false; + fWalletUnlockAnonymizeOnly = false; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; nOrderPosNext = 0; @@ -127,6 +129,7 @@ class CWallet : public CCryptoKeyStore nWalletMaxVersion = FEATURE_BASE; strWalletFile = strWalletFileIn; fFileBacked = true; + fWalletUnlockAnonymizeOnly = false; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; nOrderPosNext = 0; @@ -171,7 +174,7 @@ class CWallet : public CCryptoKeyStore bool AddCScript(const CScript& redeemScript); bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); } - bool Unlock(const SecureString& strWalletPassphrase); + bool Unlock(const SecureString& strWalletPassphrase, bool anonimizeOnly = false); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase);