Skip to content

Commit

Permalink
Added unlock for staking only feature #44 (#121)
Browse files Browse the repository at this point in the history
* Development new (#113)

* Updated segwit deployment time for testnet

* Updated genesis for testnet, changed segwit deployment time

* Uptdating segwit starttime for TestNet

* Need more time on segwit starttime for TestNet

* Final test segwit starttime for TestNet

* Added -clearmncache as allowed arg (#95)

* Fixed rescaning of wallet when refreshing tposcontract (#97)

* Fixed compilation issue on CentOS 7 (#98)

* Added slot for handling click on "toogle locked state" button in coincontrolldialog (#99)

* Fixed RPC call for getblock to show tposcontract

* Prepared for 1.0.14 release

Updated version to 1.0.14, updated build type to "release"

* Changed IS_RELEASE to false

* Bugfix/103 (#105)

* Fixed tposcontract cleanup issue, fixed typo mistakes in UI

* Fixed issue with filtering MintedTPoS, fixed issue with sendtoadress with amount of splits

* bugfix/101 (#102)

* Added setstakesplitthreshold into vRPCConvertParams

* Update sync.h

* Updated staking settings startup param

* Updated version to 1.0.15

* Added tpos commission as filter option

* Fix crash bug with duplicate inputs within a transaction

* Increased version to 16

* Adding #include <QButtonGroup> (#116)

Adding #include <QButtonGroup>

* Development new (#117)

* Updated testnet with new genesis

* Fixed spelling. Added rpc call converter

* Fixed intro message

* Removed dumpwallet from RPC calls

* Changed links for license text

* Updated README links

* Changed version to 1.0.17

* Added authhelper for dumpprivkey

* add docker image

* fixed entrypoint in Dockerfile, added instructions to README.md

* aligned README.md format

* changed user name and image name

* Update README.md

* Added encrypt wallet and staking only feature

* Tpos will now also be asked if staking only is enabled

* del unnecessary import in .cpp make comment doxygen conform in .h
  • Loading branch information
Simon Sorgenfrei authored and durkmurder committed Jan 22, 2019
1 parent 0db46ae commit b4e4bb5
Show file tree
Hide file tree
Showing 16 changed files with 113 additions and 32 deletions.
3 changes: 2 additions & 1 deletion src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@ class WalletImpl : public Wallet
}
bool isCrypted() override { return m_wallet.IsCrypted(); }
bool lock() override { return m_wallet.Lock(); }
bool unlock(const SecureString& wallet_passphrase) override { return m_wallet.Unlock(wallet_passphrase); }
bool unlock(const SecureString& wallet_passphrase, bool stakingOnly = false) override { return m_wallet.Unlock(wallet_passphrase, stakingOnly); }
bool isLocked() override { return m_wallet.IsLocked(); }
bool isLockedForStaking() override { return m_wallet.fWalletUnlockStakingOnly; }
bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
const SecureString& new_wallet_passphrase) override
{
Expand Down
5 changes: 4 additions & 1 deletion src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ class Wallet
virtual bool lock() = 0;

//! Unlock wallet.
virtual bool unlock(const SecureString& wallet_passphrase) = 0;
virtual bool unlock(const SecureString& wallet_passphrase, bool stakingOnly = false) = 0;

//! Return whether wallet is locked.
virtual bool isLocked() = 0;

//! Return whether wallet is locked for Staking only.
virtual bool isLockedForStaking() = 0;

//! Change wallet passphrase.
virtual bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
Expand Down
10 changes: 8 additions & 2 deletions src/qt/askpassphrasedialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
ui->passEdit1->hide();
setWindowTitle(tr("Encrypt wallet"));
break;
case UnlockStaking:
ui->stakingCheckBox->setChecked(true);
ui->stakingCheckBox->show();
case Unlock: // Ask passphrase
ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet."));
ui->passLabel2->hide();
Expand Down Expand Up @@ -85,6 +88,7 @@ AskPassphraseDialog::~AskPassphraseDialog()
void AskPassphraseDialog::setModel(WalletModel *_model)
{
this->model = _model;
ui->stakingCheckBox->setChecked(model->isStakingOnlyUnlocked());
}

void AskPassphraseDialog::accept()
Expand Down Expand Up @@ -152,8 +156,9 @@ void AskPassphraseDialog::accept()
QDialog::reject(); // Cancelled
}
} break;
case UnlockStaking:
case Unlock:
if(!model->setWalletLocked(false, oldpass))
if(!model->setWalletLocked(false, oldpass, ui->stakingCheckBox->isChecked()))
{
QMessageBox::critical(this, tr("Wallet unlock failed"),
tr("The passphrase entered for the wallet decryption was incorrect."));
Expand Down Expand Up @@ -207,7 +212,8 @@ void AskPassphraseDialog::textChanged()
case Encrypt: // New passphrase x2
acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
break;
case Unlock: // Old passphrase x1
case UnlockStaking: // Old passphrase x1
case Unlock: // Old passphrase x1
case Decrypt:
acceptable = !ui->passEdit1->text().isEmpty();
break;
Expand Down
9 changes: 5 additions & 4 deletions src/qt/askpassphrasedialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ class AskPassphraseDialog : public QDialog

public:
enum Mode {
Encrypt, /**< Ask passphrase twice and encrypt */
Unlock, /**< Ask passphrase and unlock */
ChangePass, /**< Ask old passphrase + new passphrase twice */
Decrypt /**< Ask passphrase and decrypt wallet */
Encrypt, /**< Ask passphrase twice and encrypt */
UnlockStaking, /**< Ask passphrase and unlock for staking */
Unlock, /**< Ask passphrase and unlock */
ChangePass, /**< Ask old passphrase + new passphrase twice */
Decrypt /**< Ask passphrase and decrypt wallet */
};

explicit AskPassphraseDialog(Mode mode, QWidget *parent);
Expand Down
10 changes: 10 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,16 @@ void BitcoinGUI::setEncryptionStatus(int status)
// lockWalletAction->setVisible(true);
// encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
// break;
case WalletModel::UnlockedForStakingOnly:
labelEncryptionIcon->show();
labelEncryptionIcon->setPixmap(QIcon(":/icons/" + theme + "/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b> for staking only"));
encryptWalletAction->setChecked(true);
changePassphraseAction->setEnabled(true);
unlockWalletAction->setVisible(false);
lockWalletAction->setVisible(true);
encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
break;
case WalletModel::Locked:
labelEncryptionIcon->show();
labelEncryptionIcon->setPixmap(QIcon(":/icons/" + theme + "/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
Expand Down
19 changes: 16 additions & 3 deletions src/qt/forms/askpassphrasedialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>598</width>
<height>222</height>
<height>225</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -108,7 +108,7 @@
</property>
</widget>
</item>
<item row="4" column="0">
<item row="6" column="0">
<widget class="QCheckBox" name="mixingOnlyCheckBox">
<property name="enabled">
<bool>true</bool>
Expand All @@ -124,7 +124,20 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="0">
<widget class="QCheckBox" name="stakingCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="visible">
<bool>false</bool>
</property>
<property name="text">
<string> Unlock for staking only</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="toggleShowPasswordButton">
<property name="text">
<string>Show password</string>
Expand Down
6 changes: 3 additions & 3 deletions src/qt/masternodelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ void MasternodeList::on_startButton_clicked()

WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();

if(encStatus == walletModel->Locked) {
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForStakingOnly) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());

if(!ctx.isValid()) return; // Unlock wallet was cancelled
Expand All @@ -363,7 +363,7 @@ void MasternodeList::on_startAllButton_clicked()

WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();

if(encStatus == walletModel->Locked) {
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForStakingOnly) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());

if(!ctx.isValid()) return; // Unlock wallet was cancelled
Expand Down Expand Up @@ -395,7 +395,7 @@ void MasternodeList::on_startMissingButton_clicked()

WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();

if(encStatus == walletModel->Locked) {
if(encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForStakingOnly) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());

if(!ctx.isValid()) return; // Unlock wallet was cancelled
Expand Down
4 changes: 4 additions & 0 deletions src/qt/sendcoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,10 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.second = CClientUIInterface::MSG_ERROR;
break;
// included to prevent a compiler warning.
case WalletModel::StakingOnlyUnlocked:
QMessageBox::warning(this, tr("Send Coins"),
tr("Error: The wallet was unlocked only for staking coins."),
QMessageBox::Ok, QMessageBox::Ok);
case WalletModel::OK:
default:
return;
Expand Down
7 changes: 4 additions & 3 deletions src/qt/tpospage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ void TPoSPage::onStakeClicked()
sendToTPoSAddress(tposAddress);
}
};

if (_walletModel->getEncryptionStatus() == WalletModel::Locked)
WalletModel::EncryptionStatus encStatus = _walletModel->getEncryptionStatus();
if (encStatus == WalletModel::Locked || encStatus == _walletModel->UnlockedForStakingOnly)
{
WalletModel::UnlockContext ctx(_walletModel->requestUnlock());
if (!ctx.isValid())
Expand Down Expand Up @@ -270,7 +270,8 @@ void TPoSPage::onCancelClicked()

try
{
if (_walletModel->getEncryptionStatus() == WalletModel::Locked)
WalletModel::EncryptionStatus encStatus = _walletModel->getEncryptionStatus();
if (encStatus == WalletModel::Locked || encStatus == _walletModel->UnlockedForStakingOnly)
{
WalletModel::UnlockContext ctx(_walletModel->requestUnlock());
if (!ctx.isValid())
Expand Down
30 changes: 27 additions & 3 deletions src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,15 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
return OK;
}

if (isStakingOnlyUnlocked())
{
return StakingOnlyUnlocked;
}

QSet<QString> setAddress; // Used to detect duplicates
int nAddresses = 0;

// Pre-check input data for validity
for (const SendCoinsRecipient &rcp : recipients)
{
Expand Down Expand Up @@ -233,6 +238,10 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction)
{
QByteArray transaction_array; /* store serialized transaction */

if (isStakingOnlyUnlocked()) {
return StakingOnlyUnlocked;
}

{
std::vector<std::pair<std::string, std::string>> vOrderForm;
Expand Down Expand Up @@ -331,6 +340,10 @@ WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
{
return Locked;
}
else if(m_wallet->isLockedForStaking())
{
return UnlockedForStakingOnly;
}
else
{
return Unlocked;
Expand All @@ -351,7 +364,7 @@ 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 stakingOnly)
{
if(locked)
{
Expand All @@ -361,10 +374,15 @@ bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
else
{
// Unlock
return m_wallet->unlock(passPhrase);
return m_wallet->unlock(passPhrase, stakingOnly);
}
}

bool WalletModel::isStakingOnlyUnlocked()
{
return m_wallet->isLockedForStaking();
}

bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
{
m_wallet->lock(); // Make sure wallet is locked before attempting pass change
Expand Down Expand Up @@ -440,6 +458,12 @@ void WalletModel::unsubscribeFromCoreSignals()
WalletModel::UnlockContext WalletModel::requestUnlock()
{
bool was_locked = getEncryptionStatus() == Locked;

if (!was_locked && isStakingOnlyUnlocked()) {
setWalletLocked(true);
was_locked = getEncryptionStatus() == Locked;
}

if(was_locked)
{
// Request UI to unlock wallet
Expand Down
14 changes: 9 additions & 5 deletions src/qt/walletmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,16 @@ class WalletModel : public QObject
TransactionCreationFailed, // Error returned when wallet is still locked
TransactionCommitFailed,
AbsurdFee,
PaymentRequestExpired
PaymentRequestExpired,
StakingOnlyUnlocked
};

enum EncryptionStatus
{
Unencrypted, // !wallet->IsCrypted()
Locked, // wallet->IsCrypted() && wallet->IsLocked()
Unlocked // wallet->IsCrypted() && !wallet->IsLocked()
Unencrypted, // !wallet->IsCrypted()
Locked, // wallet->IsCrypted() && wallet->IsLocked()
Unlocked, // wallet->IsCrypted() && !wallet->IsLocked()
UnlockedForStakingOnly // wallet->IsCrypted() && !wallet->IsLocked() && wallet->fWalletUnlockStakingOnly
};

OptionsModel *getOptionsModel();
Expand Down Expand Up @@ -168,8 +170,10 @@ 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 stakingOnly = false);
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
// Is wallet unlocked for staking only?
bool isStakingOnlyUnlocked();

// RAI object for unlocking wallet, returned by requestUnlock()
class UnlockContext
Expand Down
4 changes: 2 additions & 2 deletions src/qt/walletview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,9 @@ 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::UnlockedForStakingOnly)
{
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
AskPassphraseDialog dlg(AskPassphraseDialog::UnlockStaking, this);
dlg.setModel(walletModel);
dlg.exec();
}
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request)


UniValue dumpwallet(const JSONRPCRequest& request)
{
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
Expand Down
11 changes: 9 additions & 2 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)

void EnsureWalletIsUnlocked(CWallet * const pwallet)
{
if (pwallet->IsLocked()) {
if (pwallet->IsLocked() || pwallet->fWalletUnlockStakingOnly) {
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
}
}
Expand Down Expand Up @@ -2549,10 +2549,17 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
if (nSleepTime > MAX_SLEEP_TIME) {
nSleepTime = MAX_SLEEP_TIME;
}

bool stakingOnly = false;
if (request.params.size() == 3)
stakingOnly = request.params[2].get_bool();

if (!pwallet->IsLocked() && pwallet->fWalletUnlockStakingOnly && stakingOnly)
throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked.");

if (strWalletPass.length() > 0)
{
if (!pwallet->Unlock(strWalletPass)) {
if (!pwallet->Unlock(strWalletPass, stakingOnly)) {
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,13 @@ bool CWallet::LoadWatchOnly(const CScript &dest)
return CCryptoKeyStore::AddWatchOnly(dest);
}

bool CWallet::Unlock(const SecureString& strWalletPassphrase)
bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool stakingOnly)
{
if (!IsLocked()) {
fWalletUnlockStakingOnly = stakingOnly;
return true;
}

CCrypter crypter;
CKeyingMaterial _vMasterKey;

Expand All @@ -559,6 +564,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
continue; // try another master key
if (CCryptoKeyStore::Unlock(_vMasterKey))
fWalletUnlockStakingOnly = stakingOnly;
return true;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface

bool GetMasternodeOutpointAndKeys(COutPoint& outpointRet, CPubKey& pubKeyRet, CKey& keyRet, std::string strTxHash, std::string strOutputIndex);

bool fWalletUnlockStakingOnly = false;
/** Get a name for this wallet for logging/debugging purposes.
*/
const std::string& GetName() const { return m_name; }
Expand Down Expand Up @@ -979,7 +980,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
int64_t nRelockTime = 0;

bool Unlock(const SecureString& strWalletPassphrase);
bool Unlock(const SecureString& strWalletPassphrase, bool stakingOnly = false);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);

Expand Down

0 comments on commit b4e4bb5

Please sign in to comment.