mirror of
https://github.com/monero-project/monero-gui.git
synced 2025-01-03 09:29:38 +00:00
trezor: support new passphrase entry mechanism
- passphrase can be prompted also when wallet is running (thus added to the wallet listener) - device/host decision is now made on the host
This commit is contained in:
parent
38612c1285
commit
86d21a34ba
15 changed files with 732 additions and 133 deletions
104
components/DevicePassphraseDialog.qml
Normal file
104
components/DevicePassphraseDialog.qml
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
import "." as MoneroComponents
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var onAcceptedCallback
|
||||||
|
property var onWalletEntryCallback
|
||||||
|
property var onRejectedCallback
|
||||||
|
|
||||||
|
function open(canEnterOnDevice_) {
|
||||||
|
var canEnterOnDevice = canEnterOnDevice_ !== null ? canEnterOnDevice_ : canEnterOnDevice
|
||||||
|
root.visible = true;
|
||||||
|
|
||||||
|
if (canEnterOnDevice) {
|
||||||
|
entryChooserDialog.okText = qsTr("Hardware wallet")
|
||||||
|
entryChooserDialog.cancelText = qsTr("Computer")
|
||||||
|
entryChooserDialog.open()
|
||||||
|
} else {
|
||||||
|
openPassphraseDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPassphraseDialog() {
|
||||||
|
root.visible = true
|
||||||
|
passphraseDialog.openPassphraseDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
root.visible = false;
|
||||||
|
if (entryChooserDialog.visible)
|
||||||
|
entryChooserDialog.close()
|
||||||
|
if (passphraseDialog.visible)
|
||||||
|
passphraseDialog.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardDialog {
|
||||||
|
id: entryChooserDialog
|
||||||
|
title: qsTr("Hardware wallet passphrase") + translationManager.emptyString
|
||||||
|
text: qsTr("Please select where you want to enter passphrase.\nIt is recommended to enter passphrase on the hardware wallet for better security.") + translationManager.emptyString
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
if (onWalletEntryCallback){
|
||||||
|
onWalletEntryCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRejected: {
|
||||||
|
openPassphraseDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloseCallback: {
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PasswordDialog {
|
||||||
|
id: passphraseDialog
|
||||||
|
anchors.fill: parent
|
||||||
|
passphraseDialogMode: true
|
||||||
|
|
||||||
|
onAcceptedPassphrase: {
|
||||||
|
if (onAcceptedCallback)
|
||||||
|
onAcceptedCallback(passphraseDialog.password);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRejectedPassphrase: {
|
||||||
|
if (onRejectedCallback)
|
||||||
|
onRejectedCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloseCallback: {
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
main.qml
48
main.qml
|
@ -293,6 +293,7 @@ ApplicationWindow {
|
||||||
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
|
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
|
||||||
currentWallet.deviceButtonRequest.disconnect(onDeviceButtonRequest);
|
currentWallet.deviceButtonRequest.disconnect(onDeviceButtonRequest);
|
||||||
currentWallet.deviceButtonPressed.disconnect(onDeviceButtonPressed);
|
currentWallet.deviceButtonPressed.disconnect(onDeviceButtonPressed);
|
||||||
|
currentWallet.walletPassphraseNeeded.disconnect(onWalletPassphraseNeededWallet);
|
||||||
currentWallet.transactionCommitted.disconnect(onTransactionCommitted);
|
currentWallet.transactionCommitted.disconnect(onTransactionCommitted);
|
||||||
middlePanel.paymentClicked.disconnect(handlePayment);
|
middlePanel.paymentClicked.disconnect(handlePayment);
|
||||||
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
|
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
|
||||||
|
@ -360,6 +361,7 @@ ApplicationWindow {
|
||||||
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
|
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
|
||||||
currentWallet.deviceButtonRequest.connect(onDeviceButtonRequest);
|
currentWallet.deviceButtonRequest.connect(onDeviceButtonRequest);
|
||||||
currentWallet.deviceButtonPressed.connect(onDeviceButtonPressed);
|
currentWallet.deviceButtonPressed.connect(onDeviceButtonPressed);
|
||||||
|
currentWallet.walletPassphraseNeeded.connect(onWalletPassphraseNeededWallet);
|
||||||
currentWallet.transactionCommitted.connect(onTransactionCommitted);
|
currentWallet.transactionCommitted.connect(onTransactionCommitted);
|
||||||
middlePanel.paymentClicked.connect(handlePayment);
|
middlePanel.paymentClicked.connect(handlePayment);
|
||||||
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
|
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
|
||||||
|
@ -558,19 +560,32 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletPassphraseNeeded(){
|
function onWalletPassphraseNeededManager(on_device){
|
||||||
|
onWalletPassphraseNeeded(walletManager, on_device)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWalletPassphraseNeededWallet(on_device){
|
||||||
|
onWalletPassphraseNeeded(currentWallet, on_device)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWalletPassphraseNeeded(handler, on_device){
|
||||||
hideProcessingSplash();
|
hideProcessingSplash();
|
||||||
|
|
||||||
console.log(">>> wallet passphrase needed: ")
|
console.log(">>> wallet passphrase needed: ")
|
||||||
passwordDialog.onAcceptedPassphraseCallback = function() {
|
devicePassphraseDialog.onAcceptedCallback = function(passphrase) {
|
||||||
walletManager.onPassphraseEntered(passwordDialog.password);
|
handler.onPassphraseEntered(passphrase, false, false);
|
||||||
appWindow.onWalletOpening();
|
appWindow.onWalletOpening();
|
||||||
}
|
}
|
||||||
passwordDialog.onRejectedPassphraseCallback = function() {
|
devicePassphraseDialog.onWalletEntryCallback = function() {
|
||||||
walletManager.onPassphraseEntered("", true);
|
handler.onPassphraseEntered("", true, false);
|
||||||
appWindow.onWalletOpening();
|
appWindow.onWalletOpening();
|
||||||
}
|
}
|
||||||
passwordDialog.openPassphraseDialog()
|
devicePassphraseDialog.onRejectedCallback = function() {
|
||||||
|
handler.onPassphraseEntered("", false, true);
|
||||||
|
appWindow.onWalletOpening();
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePassphraseDialog.open(on_device)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletUpdate() {
|
function onWalletUpdate() {
|
||||||
|
@ -1295,7 +1310,7 @@ ApplicationWindow {
|
||||||
walletManager.deviceButtonRequest.connect(onDeviceButtonRequest);
|
walletManager.deviceButtonRequest.connect(onDeviceButtonRequest);
|
||||||
walletManager.deviceButtonPressed.connect(onDeviceButtonPressed);
|
walletManager.deviceButtonPressed.connect(onDeviceButtonPressed);
|
||||||
walletManager.checkUpdatesComplete.connect(onWalletCheckUpdatesComplete);
|
walletManager.checkUpdatesComplete.connect(onWalletCheckUpdatesComplete);
|
||||||
walletManager.walletPassphraseNeeded.connect(onWalletPassphraseNeeded);
|
walletManager.walletPassphraseNeeded.connect(onWalletPassphraseNeededManager);
|
||||||
IPC.uriHandler.connect(onUriHandler);
|
IPC.uriHandler.connect(onUriHandler);
|
||||||
|
|
||||||
if(typeof daemonManager != "undefined") {
|
if(typeof daemonManager != "undefined") {
|
||||||
|
@ -1512,8 +1527,6 @@ ApplicationWindow {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
property var onAcceptedCallback
|
property var onAcceptedCallback
|
||||||
property var onRejectedCallback
|
property var onRejectedCallback
|
||||||
property var onAcceptedPassphraseCallback
|
|
||||||
property var onRejectedPassphraseCallback
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
if (onAcceptedCallback)
|
if (onAcceptedCallback)
|
||||||
onAcceptedCallback();
|
onAcceptedCallback();
|
||||||
|
@ -1537,14 +1550,13 @@ ApplicationWindow {
|
||||||
informationPopup.open();
|
informationPopup.open();
|
||||||
}
|
}
|
||||||
onRejectedNewPassword: {}
|
onRejectedNewPassword: {}
|
||||||
onAcceptedPassphrase: {
|
}
|
||||||
if (onAcceptedPassphraseCallback)
|
|
||||||
onAcceptedPassphraseCallback();
|
DevicePassphraseDialog {
|
||||||
}
|
id: devicePassphraseDialog
|
||||||
onRejectedPassphrase: {
|
visible: false
|
||||||
if (onRejectedPassphraseCallback)
|
z: parent.z + 1
|
||||||
onRejectedPassphraseCallback();
|
anchors.fill: parent
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputDialog {
|
InputDialog {
|
||||||
|
@ -1708,7 +1720,7 @@ ApplicationWindow {
|
||||||
anchors.fill: blurredArea
|
anchors.fill: blurredArea
|
||||||
source: blurredArea
|
source: blurredArea
|
||||||
radius: 64
|
radius: 64
|
||||||
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible
|
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ HEADERS += \
|
||||||
src/main/oscursor.h \
|
src/main/oscursor.h \
|
||||||
src/libwalletqt/WalletManager.h \
|
src/libwalletqt/WalletManager.h \
|
||||||
src/libwalletqt/Wallet.h \
|
src/libwalletqt/Wallet.h \
|
||||||
|
src/libwalletqt/PassphraseHelper.h \
|
||||||
src/libwalletqt/PendingTransaction.h \
|
src/libwalletqt/PendingTransaction.h \
|
||||||
src/libwalletqt/TransactionHistory.h \
|
src/libwalletqt/TransactionHistory.h \
|
||||||
src/libwalletqt/TransactionInfo.h \
|
src/libwalletqt/TransactionInfo.h \
|
||||||
|
@ -91,7 +92,9 @@ SOURCES += src/main/main.cpp \
|
||||||
src/main/clipboardAdapter.cpp \
|
src/main/clipboardAdapter.cpp \
|
||||||
src/main/oscursor.cpp \
|
src/main/oscursor.cpp \
|
||||||
src/libwalletqt/WalletManager.cpp \
|
src/libwalletqt/WalletManager.cpp \
|
||||||
|
src/libwalletqt/WalletListenerImpl.cpp \
|
||||||
src/libwalletqt/Wallet.cpp \
|
src/libwalletqt/Wallet.cpp \
|
||||||
|
src/libwalletqt/PassphraseHelper.cpp \
|
||||||
src/libwalletqt/PendingTransaction.cpp \
|
src/libwalletqt/PendingTransaction.cpp \
|
||||||
src/libwalletqt/TransactionHistory.cpp \
|
src/libwalletqt/TransactionHistory.cpp \
|
||||||
src/libwalletqt/TransactionInfo.cpp \
|
src/libwalletqt/TransactionInfo.cpp \
|
||||||
|
|
1
qml.qrc
1
qml.qrc
|
@ -99,6 +99,7 @@
|
||||||
<file>components/ProcessingSplash.qml</file>
|
<file>components/ProcessingSplash.qml</file>
|
||||||
<file>components/ProgressBar.qml</file>
|
<file>components/ProgressBar.qml</file>
|
||||||
<file>components/StandardDialog.qml</file>
|
<file>components/StandardDialog.qml</file>
|
||||||
|
<file>components/DevicePassphraseDialog.qml</file>
|
||||||
<file>pages/Sign.qml</file>
|
<file>pages/Sign.qml</file>
|
||||||
<file>components/DaemonManagerDialog.qml</file>
|
<file>components/DaemonManagerDialog.qml</file>
|
||||||
<file>version.js</file>
|
<file>version.js</file>
|
||||||
|
|
|
@ -15,7 +15,9 @@ file(GLOB SOURCE_FILES
|
||||||
"main/*.h"
|
"main/*.h"
|
||||||
"main/*.cpp"
|
"main/*.cpp"
|
||||||
"libwalletqt/WalletManager.cpp"
|
"libwalletqt/WalletManager.cpp"
|
||||||
|
"libwalletqt/WalletListenerImpl.cpp"
|
||||||
"libwalletqt/Wallet.cpp"
|
"libwalletqt/Wallet.cpp"
|
||||||
|
"libwalletqt/PassphraseHelper.cpp"
|
||||||
"libwalletqt/PendingTransaction.cpp"
|
"libwalletqt/PendingTransaction.cpp"
|
||||||
"libwalletqt/TransactionHistory.cpp"
|
"libwalletqt/TransactionHistory.cpp"
|
||||||
"libwalletqt/TransactionInfo.cpp"
|
"libwalletqt/TransactionInfo.cpp"
|
||||||
|
@ -29,6 +31,7 @@ file(GLOB SOURCE_FILES
|
||||||
"libwalletqt/UnsignedTransaction.cpp"
|
"libwalletqt/UnsignedTransaction.cpp"
|
||||||
"libwalletqt/WalletManager.h"
|
"libwalletqt/WalletManager.h"
|
||||||
"libwalletqt/Wallet.h"
|
"libwalletqt/Wallet.h"
|
||||||
|
"libwalletqt/PassphraseHelper.h"
|
||||||
"libwalletqt/PendingTransaction.h"
|
"libwalletqt/PendingTransaction.h"
|
||||||
"libwalletqt/TransactionHistory.h"
|
"libwalletqt/TransactionHistory.h"
|
||||||
"libwalletqt/TransactionInfo.h"
|
"libwalletqt/TransactionInfo.h"
|
||||||
|
|
70
src/libwalletqt/PassphraseHelper.cpp
Normal file
70
src/libwalletqt/PassphraseHelper.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "PassphraseHelper.h"
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
Monero::optional<std::string> PassphraseHelper::onDevicePassphraseRequest(bool & on_device)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
QMutexLocker locker(&m_mutex_pass);
|
||||||
|
m_passphrase_on_device = true;
|
||||||
|
m_passphrase_abort = false;
|
||||||
|
|
||||||
|
if (m_prompter != nullptr){
|
||||||
|
m_prompter->onWalletPassphraseNeeded(on_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cond_pass.wait(&m_mutex_pass);
|
||||||
|
|
||||||
|
if (m_passphrase_abort)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Passphrase entry abort");
|
||||||
|
}
|
||||||
|
|
||||||
|
on_device = m_passphrase_on_device;
|
||||||
|
if (!on_device) {
|
||||||
|
auto tmpPass = m_passphrase.toStdString();
|
||||||
|
m_passphrase = QString();
|
||||||
|
return Monero::optional<std::string>(tmpPass);
|
||||||
|
} else {
|
||||||
|
return Monero::optional<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PassphraseHelper::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
QMutexLocker locker(&m_mutex_pass);
|
||||||
|
m_passphrase = passphrase;
|
||||||
|
m_passphrase_abort = entry_abort;
|
||||||
|
m_passphrase_on_device = enter_on_device;
|
||||||
|
|
||||||
|
m_cond_pass.wakeAll();
|
||||||
|
}
|
74
src/libwalletqt/PassphraseHelper.h
Normal file
74
src/libwalletqt/PassphraseHelper.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef MONERO_GUI_PASSPHRASEHELPER_H
|
||||||
|
#define MONERO_GUI_PASSPHRASEHELPER_H
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements component responsible for showing entry prompt to the user,
|
||||||
|
* typically Wallet / Wallet manager.
|
||||||
|
*/
|
||||||
|
class PassprasePrompter {
|
||||||
|
public:
|
||||||
|
virtual void onWalletPassphraseNeeded(bool onDevice) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements receiver of the passphrase responsible for passing it back to the wallet,
|
||||||
|
* typically wallet listener.
|
||||||
|
*/
|
||||||
|
class PassphraseReceiver {
|
||||||
|
public:
|
||||||
|
virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PassphraseHelper {
|
||||||
|
public:
|
||||||
|
PassphraseHelper(PassprasePrompter * prompter=nullptr): m_prompter(prompter) {};
|
||||||
|
PassphraseHelper(const PassphraseHelper & h): PassphraseHelper(h.m_prompter) {};
|
||||||
|
Monero::optional<std::string> onDevicePassphraseRequest(bool & on_device);
|
||||||
|
void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PassprasePrompter * m_prompter;
|
||||||
|
QWaitCondition m_cond_pass;
|
||||||
|
QMutex m_mutex_pass;
|
||||||
|
QString m_passphrase;
|
||||||
|
bool m_passphrase_abort;
|
||||||
|
bool m_passphrase_on_device;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //MONERO_GUI_PASSPHRASEHELPER_H
|
|
@ -58,66 +58,6 @@ namespace {
|
||||||
static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] ="gui.subaddress_account";
|
static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] ="gui.subaddress_account";
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletListenerImpl : public Monero::WalletListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WalletListenerImpl(Wallet * w)
|
|
||||||
: m_wallet(w)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void moneySpent(const std::string &txId, uint64_t amount) override
|
|
||||||
{
|
|
||||||
qDebug() << __FUNCTION__;
|
|
||||||
emit m_wallet->moneySpent(QString::fromStdString(txId), amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void moneyReceived(const std::string &txId, uint64_t amount) override
|
|
||||||
{
|
|
||||||
qDebug() << __FUNCTION__;
|
|
||||||
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override
|
|
||||||
{
|
|
||||||
qDebug() << __FUNCTION__;
|
|
||||||
emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void newBlock(uint64_t height) override
|
|
||||||
{
|
|
||||||
// qDebug() << __FUNCTION__;
|
|
||||||
emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void updated() override
|
|
||||||
{
|
|
||||||
emit m_wallet->updated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when wallet refreshed by background thread or explicitly
|
|
||||||
virtual void refreshed() override
|
|
||||||
{
|
|
||||||
qDebug() << __FUNCTION__;
|
|
||||||
emit m_wallet->refreshed();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onDeviceButtonRequest(uint64_t code) override
|
|
||||||
{
|
|
||||||
emit m_wallet->deviceButtonRequest(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onDeviceButtonPressed() override
|
|
||||||
{
|
|
||||||
emit m_wallet->deviceButtonPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Wallet * m_wallet;
|
|
||||||
};
|
|
||||||
|
|
||||||
Wallet::Wallet(QObject * parent)
|
Wallet::Wallet(QObject * parent)
|
||||||
: Wallet(nullptr, parent)
|
: Wallet(nullptr, parent)
|
||||||
{
|
{
|
||||||
|
@ -1021,6 +961,19 @@ void Wallet::keyReuseMitigation2(bool mitigation)
|
||||||
m_walletImpl->keyReuseMitigation2(mitigation);
|
m_walletImpl->keyReuseMitigation2(mitigation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wallet::onWalletPassphraseNeeded(bool on_device)
|
||||||
|
{
|
||||||
|
emit this->walletPassphraseNeeded(on_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
|
||||||
|
{
|
||||||
|
if (m_walletListener != nullptr)
|
||||||
|
{
|
||||||
|
m_walletListener->onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_walletImpl(w)
|
, m_walletImpl(w)
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
#include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here;
|
#include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here;
|
||||||
#include "UnsignedTransaction.h"
|
#include "UnsignedTransaction.h"
|
||||||
#include "NetworkType.h"
|
#include "NetworkType.h"
|
||||||
|
#include "PassphraseHelper.h"
|
||||||
|
#include "WalletListenerImpl.h"
|
||||||
|
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
struct Wallet; // forward declaration
|
struct Wallet; // forward declaration
|
||||||
|
@ -57,7 +59,7 @@ class SubaddressModel;
|
||||||
class SubaddressAccount;
|
class SubaddressAccount;
|
||||||
class SubaddressAccountModel;
|
class SubaddressAccountModel;
|
||||||
|
|
||||||
class Wallet : public QObject
|
class Wallet : public QObject, public PassprasePrompter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
|
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
|
||||||
|
@ -348,6 +350,10 @@ public:
|
||||||
Q_INVOKABLE void segregationHeight(quint64 height);
|
Q_INVOKABLE void segregationHeight(quint64 height);
|
||||||
Q_INVOKABLE void keyReuseMitigation2(bool mitigation);
|
Q_INVOKABLE void keyReuseMitigation2(bool mitigation);
|
||||||
|
|
||||||
|
// Passphrase entry for hardware wallets
|
||||||
|
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
|
||||||
|
virtual void onWalletPassphraseNeeded(bool on_device) override;
|
||||||
|
|
||||||
// TODO: setListenter() when it implemented in API
|
// TODO: setListenter() when it implemented in API
|
||||||
signals:
|
signals:
|
||||||
// emitted on every event happened with wallet
|
// emitted on every event happened with wallet
|
||||||
|
@ -367,6 +373,7 @@ signals:
|
||||||
void walletCreationHeightChanged();
|
void walletCreationHeightChanged();
|
||||||
void deviceButtonRequest(quint64 buttonCode);
|
void deviceButtonRequest(quint64 buttonCode);
|
||||||
void deviceButtonPressed();
|
void deviceButtonPressed();
|
||||||
|
void walletPassphraseNeeded(bool onDevice);
|
||||||
void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
|
void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
|
||||||
void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const;
|
void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const;
|
||||||
void deviceShowAddressShowed();
|
void deviceShowAddressShowed();
|
||||||
|
@ -432,7 +439,7 @@ private:
|
||||||
bool m_connectionStatusRunning;
|
bool m_connectionStatusRunning;
|
||||||
QString m_daemonUsername;
|
QString m_daemonUsername;
|
||||||
QString m_daemonPassword;
|
QString m_daemonPassword;
|
||||||
Monero::WalletListener *m_walletListener;
|
WalletListenerImpl *m_walletListener;
|
||||||
FutureScheduler m_scheduler;
|
FutureScheduler m_scheduler;
|
||||||
QMutex m_storeMutex;
|
QMutex m_storeMutex;
|
||||||
};
|
};
|
||||||
|
|
97
src/libwalletqt/WalletListenerImpl.cpp
Normal file
97
src/libwalletqt/WalletListenerImpl.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "WalletListenerImpl.h"
|
||||||
|
#include "Wallet.h"
|
||||||
|
|
||||||
|
WalletListenerImpl::WalletListenerImpl(Wallet * w)
|
||||||
|
: m_wallet(w)
|
||||||
|
, m_phelper(w)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::moneySpent(const std::string &txId, uint64_t amount)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->moneySpent(QString::fromStdString(txId), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::moneyReceived(const std::string &txId, uint64_t amount)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::newBlock(uint64_t height)
|
||||||
|
{
|
||||||
|
// qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::updated()
|
||||||
|
{
|
||||||
|
emit m_wallet->updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
// called when wallet refreshed by background thread or explicitly
|
||||||
|
void WalletListenerImpl::refreshed()
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->refreshed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::onDeviceButtonRequest(uint64_t code)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->deviceButtonRequest(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::onDeviceButtonPressed()
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_wallet->deviceButtonPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletListenerImpl::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
m_phelper.onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
|
}
|
||||||
|
|
||||||
|
Monero::optional<std::string> WalletListenerImpl::onDevicePassphraseRequest(bool & on_device)
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
return m_phelper.onDevicePassphraseRequest(on_device);
|
||||||
|
}
|
68
src/libwalletqt/WalletListenerImpl.h
Normal file
68
src/libwalletqt/WalletListenerImpl.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef MONERO_GUI_WALLETLISTENERIMPL_H
|
||||||
|
#define MONERO_GUI_WALLETLISTENERIMPL_H
|
||||||
|
|
||||||
|
#include "wallet/api/wallet2_api.h"
|
||||||
|
#include "PassphraseHelper.h"
|
||||||
|
|
||||||
|
class Wallet;
|
||||||
|
|
||||||
|
class WalletListenerImpl : public Monero::WalletListener, public PassphraseReceiver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WalletListenerImpl(Wallet * w);
|
||||||
|
|
||||||
|
virtual void moneySpent(const std::string &txId, uint64_t amount) override;
|
||||||
|
|
||||||
|
virtual void moneyReceived(const std::string &txId, uint64_t amount) override;
|
||||||
|
|
||||||
|
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override;
|
||||||
|
|
||||||
|
virtual void newBlock(uint64_t height) override;
|
||||||
|
|
||||||
|
virtual void updated() override;
|
||||||
|
|
||||||
|
// called when wallet refreshed by background thread or explicitly
|
||||||
|
virtual void refreshed() override;
|
||||||
|
|
||||||
|
virtual void onDeviceButtonRequest(uint64_t code) override;
|
||||||
|
|
||||||
|
virtual void onDeviceButtonPressed() override;
|
||||||
|
|
||||||
|
virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) override;
|
||||||
|
|
||||||
|
virtual Monero::optional<std::string> onDevicePassphraseRequest(bool & on_device) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Wallet * m_wallet;
|
||||||
|
PassphraseHelper m_phelper;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //MONERO_GUI_WALLETLISTENERIMPL_H
|
|
@ -42,11 +42,12 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "qt/updater.h"
|
#include "qt/updater.h"
|
||||||
|
#include "qt/ScopeGuard.h"
|
||||||
|
|
||||||
class WalletPassphraseListenerImpl : public Monero::WalletListener
|
class WalletPassphraseListenerImpl : public Monero::WalletListener, public PassphraseReceiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_wallet(nullptr) {}
|
WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_phelper(mgr) {}
|
||||||
|
|
||||||
virtual void moneySpent(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
virtual void moneySpent(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
virtual void moneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
virtual void moneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
|
@ -55,43 +56,33 @@ public:
|
||||||
virtual void updated() override {};
|
virtual void updated() override {};
|
||||||
virtual void refreshed() override {};
|
virtual void refreshed() override {};
|
||||||
|
|
||||||
virtual Monero::optional<std::string> onDevicePassphraseRequest(bool on_device) override
|
virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) override
|
||||||
{
|
{
|
||||||
qDebug() << __FUNCTION__;
|
qDebug() << __FUNCTION__;
|
||||||
if (on_device) return Monero::optional<std::string>();
|
m_phelper.onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
|
}
|
||||||
|
|
||||||
m_mgr->onWalletPassphraseNeeded(m_wallet);
|
virtual Monero::optional<std::string> onDevicePassphraseRequest(bool & on_device) override
|
||||||
|
{
|
||||||
if (m_mgr->m_passphrase_abort)
|
qDebug() << __FUNCTION__;
|
||||||
{
|
return m_phelper.onDevicePassphraseRequest(on_device);
|
||||||
throw std::runtime_error("Passphrase entry abort");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto tmpPass = m_mgr->m_passphrase.toStdString();
|
|
||||||
m_mgr->m_passphrase = QString();
|
|
||||||
|
|
||||||
return Monero::optional<std::string>(tmpPass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDeviceButtonRequest(uint64_t code) override
|
virtual void onDeviceButtonRequest(uint64_t code) override
|
||||||
{
|
{
|
||||||
emit m_mgr->deviceButtonRequest(code);
|
qDebug() << __FUNCTION__;
|
||||||
|
emit m_mgr->deviceButtonRequest(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDeviceButtonPressed() override
|
virtual void onDeviceButtonPressed() override
|
||||||
{
|
|
||||||
emit m_mgr->deviceButtonPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onSetWallet(Monero::Wallet * wallet) override
|
|
||||||
{
|
{
|
||||||
qDebug() << __FUNCTION__;
|
qDebug() << __FUNCTION__;
|
||||||
m_wallet = wallet;
|
emit m_mgr->deviceButtonPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WalletManager * m_mgr;
|
WalletManager * m_mgr;
|
||||||
Monero::Wallet * m_wallet;
|
PassphraseHelper m_phelper;
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletManager * WalletManager::m_instance = nullptr;
|
WalletManager * WalletManager::m_instance = nullptr;
|
||||||
|
@ -123,6 +114,13 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password,
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
WalletPassphraseListenerImpl tmpListener(this);
|
WalletPassphraseListenerImpl tmpListener(this);
|
||||||
|
m_mutex_passphraseReceiver.lock();
|
||||||
|
m_passphraseReceiver = &tmpListener;
|
||||||
|
m_mutex_passphraseReceiver.unlock();
|
||||||
|
const auto cleanup = sg::make_scope_guard([this]() noexcept {
|
||||||
|
QMutexLocker passphrase_locker(&m_mutex_passphraseReceiver);
|
||||||
|
this->m_passphraseReceiver = nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
if (m_currentWallet) {
|
if (m_currentWallet) {
|
||||||
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
||||||
|
@ -186,6 +184,13 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
WalletPassphraseListenerImpl tmpListener(this);
|
WalletPassphraseListenerImpl tmpListener(this);
|
||||||
|
m_mutex_passphraseReceiver.lock();
|
||||||
|
m_passphraseReceiver = &tmpListener;
|
||||||
|
m_mutex_passphraseReceiver.unlock();
|
||||||
|
const auto cleanup = sg::make_scope_guard([this]() noexcept {
|
||||||
|
QMutexLocker passphrase_locker(&m_mutex_passphraseReceiver);
|
||||||
|
this->m_passphraseReceiver = nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
if (m_currentWallet) {
|
if (m_currentWallet) {
|
||||||
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
||||||
|
@ -529,6 +534,7 @@ bool WalletManager::clearWalletCache(const QString &wallet_path) const
|
||||||
|
|
||||||
WalletManager::WalletManager(QObject *parent)
|
WalletManager::WalletManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
|
, m_passphraseReceiver(nullptr)
|
||||||
, m_scheduler(this)
|
, m_scheduler(this)
|
||||||
{
|
{
|
||||||
m_pimpl = Monero::WalletManagerFactory::getWalletManager();
|
m_pimpl = Monero::WalletManagerFactory::getWalletManager();
|
||||||
|
@ -539,22 +545,16 @@ WalletManager::~WalletManager()
|
||||||
m_scheduler.shutdownWaitForFinished();
|
m_scheduler.shutdownWaitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletManager::onWalletPassphraseNeeded(Monero::Wallet *)
|
void WalletManager::onWalletPassphraseNeeded(bool on_device)
|
||||||
{
|
{
|
||||||
m_mutex_pass.lock();
|
emit this->walletPassphraseNeeded(on_device);
|
||||||
m_passphrase_abort = false;
|
|
||||||
emit this->walletPassphraseNeeded();
|
|
||||||
|
|
||||||
m_cond_pass.wait(&m_mutex_pass);
|
|
||||||
m_mutex_pass.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletManager::onPassphraseEntered(const QString &passphrase, bool entry_abort)
|
void WalletManager::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
|
||||||
{
|
{
|
||||||
m_mutex_pass.lock();
|
QMutexLocker locker(&m_mutex_passphraseReceiver);
|
||||||
m_passphrase = passphrase;
|
if (m_passphraseReceiver != nullptr)
|
||||||
m_passphrase_abort = entry_abort;
|
{
|
||||||
|
m_passphraseReceiver->onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
m_cond_pass.wakeAll();
|
}
|
||||||
m_mutex_pass.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,13 +38,14 @@
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
#include "qt/FutureScheduler.h"
|
#include "qt/FutureScheduler.h"
|
||||||
#include "NetworkType.h"
|
#include "NetworkType.h"
|
||||||
|
#include "PassphraseHelper.h"
|
||||||
|
|
||||||
class Wallet;
|
class Wallet;
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
struct WalletManager;
|
struct WalletManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletManager : public QObject
|
class WalletManager : public QObject, public PassprasePrompter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool connected READ connected)
|
Q_PROPERTY(bool connected READ connected)
|
||||||
|
@ -185,14 +186,14 @@ public:
|
||||||
// clear/rename wallet cache
|
// clear/rename wallet cache
|
||||||
Q_INVOKABLE bool clearWalletCache(const QString &fileName) const;
|
Q_INVOKABLE bool clearWalletCache(const QString &fileName) const;
|
||||||
|
|
||||||
Q_INVOKABLE void onWalletPassphraseNeeded(Monero::Wallet * wallet);
|
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
|
||||||
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool entry_abort=false);
|
virtual void onWalletPassphraseNeeded(bool on_device) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void walletOpened(Wallet * wallet);
|
void walletOpened(Wallet * wallet);
|
||||||
void walletCreated(Wallet * wallet);
|
void walletCreated(Wallet * wallet);
|
||||||
void walletPassphraseNeeded();
|
void walletPassphraseNeeded(bool onDevice);
|
||||||
void deviceButtonRequest(quint64 buttonCode);
|
void deviceButtonRequest(quint64 buttonCode);
|
||||||
void deviceButtonPressed();
|
void deviceButtonPressed();
|
||||||
void checkUpdatesComplete(
|
void checkUpdatesComplete(
|
||||||
|
@ -216,12 +217,8 @@ private:
|
||||||
Monero::WalletManager * m_pimpl;
|
Monero::WalletManager * m_pimpl;
|
||||||
mutable QMutex m_mutex;
|
mutable QMutex m_mutex;
|
||||||
QPointer<Wallet> m_currentWallet;
|
QPointer<Wallet> m_currentWallet;
|
||||||
|
PassphraseReceiver * m_passphraseReceiver;
|
||||||
QWaitCondition m_cond_pass;
|
QMutex m_mutex_passphraseReceiver;
|
||||||
QMutex m_mutex_pass;
|
|
||||||
QString m_passphrase;
|
|
||||||
bool m_passphrase_abort;
|
|
||||||
|
|
||||||
FutureScheduler m_scheduler;
|
FutureScheduler m_scheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
205
src/qt/ScopeGuard.h
Normal file
205
src/qt/ScopeGuard.h
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
// Author: ricab
|
||||||
|
// Source: https://github.com/ricab/scope_guard
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
//
|
||||||
|
// In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
// of this software dedicate any and all copyright interest in the
|
||||||
|
// software to the public domain. We make this dedication for the benefit
|
||||||
|
// of the public at large and to the detriment of our heirs and
|
||||||
|
// successors. We intend this dedication to be an overt act of
|
||||||
|
// relinquishment in perpetuity of all present and future rights to this
|
||||||
|
// software under copyright law.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// For more information, please refer to <http://unlicense.org>
|
||||||
|
|
||||||
|
#ifndef SCOPE_GUARD_HPP_
|
||||||
|
#define SCOPE_GUARD_HPP_
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L && defined(SG_REQUIRE_NOEXCEPT_IN_CPP17)
|
||||||
|
#define SG_REQUIRE_NOEXCEPT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sg
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
/* --- Some custom type traits --- */
|
||||||
|
|
||||||
|
// Type trait determining whether a type is callable with no arguments
|
||||||
|
template<typename T, typename = void>
|
||||||
|
struct is_noarg_callable_t
|
||||||
|
: public std::false_type
|
||||||
|
{}; // in general, false
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_noarg_callable_t<T, decltype(std::declval<T&&>()())>
|
||||||
|
: public std::true_type
|
||||||
|
{}; // only true when call expression valid
|
||||||
|
|
||||||
|
// Type trait determining whether a no-argument callable returns void
|
||||||
|
template<typename T>
|
||||||
|
struct returns_void_t
|
||||||
|
: public std::is_same<void, decltype(std::declval<T&&>()())>
|
||||||
|
{};
|
||||||
|
|
||||||
|
/* Type trait determining whether a no-arg callable is nothrow invocable if
|
||||||
|
required. This is where SG_REQUIRE_NOEXCEPT logic is encapsulated. */
|
||||||
|
template<typename T>
|
||||||
|
struct is_nothrow_invocable_if_required_t
|
||||||
|
: public
|
||||||
|
#ifdef SG_REQUIRE_NOEXCEPT
|
||||||
|
std::is_nothrow_invocable<T> /* Note: _r variants not enough to
|
||||||
|
confirm void return: any return can be
|
||||||
|
discarded so all returns are
|
||||||
|
compatible with void */
|
||||||
|
#else
|
||||||
|
std::true_type
|
||||||
|
#endif
|
||||||
|
{};
|
||||||
|
|
||||||
|
// logic AND of two or more type traits
|
||||||
|
template<typename A, typename B, typename... C>
|
||||||
|
struct and_t : public and_t<A, and_t<B, C...>>
|
||||||
|
{}; // for more than two arguments
|
||||||
|
|
||||||
|
template<typename A, typename B>
|
||||||
|
struct and_t<A, B> : public std::conditional<A::value, B, A>::type
|
||||||
|
{}; // for two arguments
|
||||||
|
|
||||||
|
// Type trait determining whether a type is a proper scope_guard callback.
|
||||||
|
template<typename T>
|
||||||
|
struct is_proper_sg_callback_t
|
||||||
|
: public and_t<is_noarg_callable_t<T>,
|
||||||
|
returns_void_t<T>,
|
||||||
|
is_nothrow_invocable_if_required_t<T>,
|
||||||
|
std::is_nothrow_destructible<T>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
|
/* --- The actual scope_guard template --- */
|
||||||
|
|
||||||
|
template<typename Callback,
|
||||||
|
typename = typename std::enable_if<
|
||||||
|
is_proper_sg_callback_t<Callback>::value>::type>
|
||||||
|
class scope_guard;
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Now the friend maker --- */
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
detail::scope_guard<Callback> make_scope_guard(Callback&& callback)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value); /*
|
||||||
|
we need this in the inner namespace due to MSVC bugs preventing
|
||||||
|
sg::detail::scope_guard from befriending a sg::make_scope_guard
|
||||||
|
template instance in the parent namespace (see https://is.gd/xFfFhE). */
|
||||||
|
|
||||||
|
|
||||||
|
/* --- The template specialization that actually defines the class --- */
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
class scope_guard<Callback> final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Callback callback_type;
|
||||||
|
|
||||||
|
scope_guard(scope_guard&& other)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value);
|
||||||
|
|
||||||
|
~scope_guard() noexcept; // highlight noexcept dtor
|
||||||
|
|
||||||
|
void dismiss() noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
scope_guard() = delete;
|
||||||
|
scope_guard(const scope_guard&) = delete;
|
||||||
|
scope_guard& operator=(const scope_guard&) = delete;
|
||||||
|
scope_guard& operator=(scope_guard&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit scope_guard(Callback&& callback)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value); /*
|
||||||
|
meant for friends only */
|
||||||
|
|
||||||
|
friend scope_guard<Callback> make_scope_guard<Callback>(Callback&&)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value); /*
|
||||||
|
only make_scope_guard can create scope_guards from scratch (i.e. non-move)
|
||||||
|
*/
|
||||||
|
|
||||||
|
private:
|
||||||
|
Callback m_callback;
|
||||||
|
bool m_active;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Now the single public maker function --- */
|
||||||
|
|
||||||
|
using detail::make_scope_guard; // see comment on declaration above
|
||||||
|
|
||||||
|
} // namespace sg
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename Callback>
|
||||||
|
sg::detail::scope_guard<Callback>::scope_guard(Callback&& callback)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value)
|
||||||
|
: m_callback(std::forward<Callback>(callback)) /* use () instead of {} because
|
||||||
|
of DR 1467 (https://is.gd/WHmWuo), which still impacts older compilers
|
||||||
|
(e.g. GCC 4.x and clang <=3.6, see https://godbolt.org/g/TE9tPJ and
|
||||||
|
https://is.gd/Tsmh8G) */
|
||||||
|
, m_active{true}
|
||||||
|
{}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename Callback>
|
||||||
|
sg::detail::scope_guard<Callback>::~scope_guard() noexcept
|
||||||
|
{
|
||||||
|
if(m_active)
|
||||||
|
m_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename Callback>
|
||||||
|
sg::detail::scope_guard<Callback>::scope_guard(scope_guard&& other)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value)
|
||||||
|
: m_callback(std::forward<Callback>(other.m_callback)) // idem
|
||||||
|
, m_active{std::move(other.m_active)}
|
||||||
|
{
|
||||||
|
other.m_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename Callback>
|
||||||
|
inline void sg::detail::scope_guard<Callback>::dismiss() noexcept
|
||||||
|
{
|
||||||
|
m_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename Callback>
|
||||||
|
inline auto sg::detail::make_scope_guard(Callback&& callback)
|
||||||
|
noexcept(std::is_nothrow_constructible<Callback, Callback&&>::value)
|
||||||
|
-> detail::scope_guard<Callback>
|
||||||
|
{
|
||||||
|
return detail::scope_guard<Callback>{std::forward<Callback>(callback)};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SCOPE_GUARD_HPP_ */
|
|
@ -490,19 +490,24 @@ Rectangle {
|
||||||
walletCreatedFromDevice(success);
|
walletCreatedFromDevice(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletPassphraseNeeded(){
|
function onWalletPassphraseNeeded(on_device){
|
||||||
splash.close()
|
splash.close()
|
||||||
|
|
||||||
console.log(">>> wallet passphrase needed: ");
|
console.log(">>> wallet passphrase needed: ");
|
||||||
passwordDialog.onAcceptedPassphraseCallback = function() {
|
devicePassphraseDialog.onAcceptedCallback = function(passphrase) {
|
||||||
walletManager.onPassphraseEntered(passwordDialog.password);
|
walletManager.onPassphraseEntered(passphrase, false, false);
|
||||||
creatingWalletDeviceSplash();
|
creatingWalletDeviceSplash();
|
||||||
}
|
}
|
||||||
passwordDialog.onRejectedPassphraseCallback = function() {
|
devicePassphraseDialog.onWalletEntryCallback = function() {
|
||||||
walletManager.onPassphraseEntered("", true);
|
walletManager.onPassphraseEntered("", true, false);
|
||||||
creatingWalletDeviceSplash();
|
creatingWalletDeviceSplash();
|
||||||
}
|
}
|
||||||
passwordDialog.openPassphraseDialog()
|
devicePassphraseDialog.onRejectedCallback = function() {
|
||||||
|
walletManager.onPassphraseEntered("", false, true);
|
||||||
|
creatingWalletDeviceSplash();
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePassphraseDialog.open(on_device)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDeviceButtonRequest(code){
|
function onDeviceButtonRequest(code){
|
||||||
|
|
Loading…
Reference in a new issue