diff --git a/main.qml b/main.qml index 7f35affa..2b3ef717 100644 --- a/main.qml +++ b/main.qml @@ -764,7 +764,11 @@ ApplicationWindow { ", address: ", address, ", message: ", message); - var result = currentWallet.getTxProof(txid, address, message); + var result; + if (address.length > 0) + result = currentWallet.getTxProof(txid, address, message); + if (!result || result.startsWith("error|")) + result = currentWallet.getSpendProof(txid, message); informationPopup.title = qsTr("Payment proof") + translationManager.emptyString; if (result.startsWith("error|")) { var errorString = result.split("|")[1]; @@ -786,12 +790,16 @@ ApplicationWindow { ", message: ", message, ", signature: ", signature); - var result = currentWallet.checkTxProof(txid, address, message, signature); + var result; + if (address.length > 0) + result = currentWallet.checkTxProof(txid, address, message, signature); + else + result = currentWallet.checkSpendProof(txid, message, signature); var results = result.split("|"); - if (results.length == 5 && results[0] == "true") { - var good = results[1] == "true"; + if (address.length > 0 && results.length == 5 && results[0] === "true") { + var good = results[1] === "true"; var received = results[2]; - var in_pool = results[3] == "true"; + var in_pool = results[3] === "true"; var confirmations = results[4]; informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString; @@ -812,6 +820,12 @@ ApplicationWindow { informationPopup.text = qsTr("This address received nothing"); } } + else if (results.length == 2 && results[0] === "true") { + var good = results[1] === "true"; + informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString; + informationPopup.icon = good ? StandardIcon.Information : StandardIcon.Critical; + informationPopup.text = good ? qsTr("Good signature") : qsTr("Bad signature"); + } else { informationPopup.title = qsTr("Error") + translationManager.emptyString; informationPopup.text = currentWallet.errorString; diff --git a/pages/TxKey.qml b/pages/TxKey.qml index 926d7e60..a996bf7f 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -72,6 +72,10 @@ Rectangle { if ((signature.length - 9) % 132 != 0) return false; return check256(signature, signature.length); + } else if (signature.startsWith("SpendProofV")) { + if ((signature.length - 12) % 88 != 0) + return false; + return check256(signature, signature.length); } return false; } @@ -90,7 +94,8 @@ Rectangle { property int lineEditFontSize: 12 Text { - text: qsTr("Generate a proof of your incoming/outgoing payment by supplying the transaction ID, the recipient address and an optional message:") + translationManager.emptyString + text: qsTr("Generate a proof of your incoming/outgoing payment by supplying the transaction ID, the recipient address and an optional message. \n" + + "For the case of outgoing payments, you can get a 'Spend Proof' that proves the authorship of a transaction. In this case, you don't need to specify the recipient address.") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true; } @@ -183,7 +188,7 @@ Rectangle { shadowPressedColor: "#B32D00" releasedColor: "#FF6C3C" pressedColor: "#FF4304" - enabled: checkTxID(getProofTxIdLine.text) && checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet) + enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) onClicked: { console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) @@ -201,7 +206,8 @@ Rectangle { } Text { - text: qsTr("Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature:") + translationManager.emptyString + text: qsTr("Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature.\n" + + "For the case with Spend Proof, you don't need to specify the recipient address.") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true; } @@ -322,7 +328,7 @@ Rectangle { shadowPressedColor: "#B32D00" releasedColor: "#FF6C3C" pressedColor: "#FF4304" - enabled: checkTxID(checkProofTxIdLine.text) && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet) && checkSignature(checkProofSignatureLine.text) + enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.startsWith("SpendProofV") && checkProofAddressLine.text.length == 0) || (!checkProofSignatureLine.text.startsWith("SpendProofV") && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) onClicked: { console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text); root.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text) diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index da7ecd9b..9dfcaef7 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -523,6 +523,22 @@ QString Wallet::checkTxProof(const QString &txid, const QString &address, const return QString::fromStdString(result); } +Q_INVOKABLE QString Wallet::getSpendProof(const QString &txid, const QString &message) const +{ + std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString()); + if (result.empty()) + result = "error|" + m_walletImpl->errorString(); + return QString::fromStdString(result); +} + +Q_INVOKABLE QString Wallet::checkSpendProof(const QString &txid, const QString &message, const QString &signature) const +{ + bool good; + bool success = m_walletImpl->checkSpendProof(txid.toStdString(), message.toStdString(), signature.toStdString(), good); + std::string result = std::string(success ? "true" : "false") + "|" + std::string(!success ? m_walletImpl->errorString() : good ? "true" : "false"); + return QString::fromStdString(result); +} + QString Wallet::signMessage(const QString &message, bool filename) const { if (filename) { diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index c653b8df..edec6130 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -235,6 +235,8 @@ public: Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address); Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const; Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); + Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const; + Q_INVOKABLE QString checkSpendProof(const QString &txid, const QString &message, const QString &signature) const; // Rescan spent outputs Q_INVOKABLE bool rescanSpent();