aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MiddlePanel.qml2
-rw-r--r--js/TxUtils.js4
-rw-r--r--main.qml54
-rw-r--r--pages/TxKey.qml51
-rw-r--r--src/libwalletqt/Wallet.cpp19
-rw-r--r--src/libwalletqt/Wallet.h2
6 files changed, 103 insertions, 29 deletions
diff --git a/MiddlePanel.qml b/MiddlePanel.qml
index 544f0244..b6e29994 100644
--- a/MiddlePanel.qml
+++ b/MiddlePanel.qml
@@ -66,7 +66,7 @@ Rectangle {
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
signal sweepUnmixableClicked()
signal generatePaymentIdInvoked()
- signal getProofClicked(string txid, string address, string message);
+ signal getProofClicked(string txid, string address, string message, string amount);
signal checkProofClicked(string txid, string address, string message, string signature);
Rectangle {
diff --git a/js/TxUtils.js b/js/TxUtils.js
index 63405338..de79b625 100644
--- a/js/TxUtils.js
+++ b/js/TxUtils.js
@@ -61,6 +61,10 @@ function checkSignature(signature) {
if ((signature.length - 12) % 88 != 0)
return false;
return check256(signature, signature.length);
+ } else if (signature.indexOf("ReserveProofV") === 0) {
+ if ((signature.length - 14) % 447 != 0)
+ return false;
+ return check256(signature, signature.length);
}
return false;
}
diff --git a/main.qml b/main.qml
index f856539a..35e41271 100644
--- a/main.qml
+++ b/main.qml
@@ -985,24 +985,28 @@ ApplicationWindow {
}
// called on "getProof"
- function handleGetProof(txid, address, message) {
- console.log("Getting payment proof: ")
- console.log("\ttxid: ", txid,
- ", address: ", address,
- ", message: ", message);
-
- function spendProofFallback(txid, result){
- if (!result || result.indexOf("error|") === 0) {
- currentWallet.getSpendProofAsync(txid, message, txProofComputed);
- } else {
- txProofComputed(txid, result);
+ function handleGetProof(txid, address, message, amount) {
+ if (amount.length > 0) {
+ var result = currentWallet.getReserveProof(false, currentWallet.currentSubaddressAccount, walletManager.amountFromString(amount), message)
+ txProofComputed(null, result)
+ } else {
+ console.log("Getting payment proof: ")
+ console.log("\ttxid: ", txid,
+ ", address: ", address,
+ ", message: ", message);
+ function spendProofFallback(txid, result){
+ if (!result || result.indexOf("error|") === 0) {
+ currentWallet.getSpendProofAsync(txid, message, txProofComputed);
+ } else {
+ txProofComputed(txid, result);
+ }
}
+ if (address.length > 0)
+ currentWallet.getTxProofAsync(txid, address, message, spendProofFallback);
+ else
+ spendProofFallback(txid, null);
}
-
- if (address.length > 0)
- currentWallet.getTxProofAsync(txid, address, message, spendProofFallback);
- else
- spendProofFallback(txid, null);
+ informationPopup.open()
}
function txProofComputed(txid, result){
@@ -1025,12 +1029,18 @@ ApplicationWindow {
", signature: ", signature);
var result;
- if (address.length > 0)
+ var isReserveProof = signature.indexOf("ReserveProofV") === 0;
+ if (address.length > 0 && !isReserveProof) {
result = currentWallet.checkTxProof(txid, address, message, signature);
- else
+ }
+ else if (isReserveProof) {
+ result = currentWallet.checkReserveProof(address, message, signature);
+ }
+ else {
result = currentWallet.checkSpendProof(txid, message, signature);
+ }
var results = result.split("|");
- if (address.length > 0 && results.length == 5 && results[0] === "true") {
+ if (address.length > 0 && results.length == 5 && results[0] === "true" && !isReserveProof) {
var good = results[1] === "true";
var received = results[2];
var in_pool = results[3] === "true";
@@ -1058,6 +1068,12 @@ ApplicationWindow {
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 if (isReserveProof && results[0] === "true") {
+ var good = results[1] === "true";
+ informationPopup.title = qsTr("Reserve proof check") + translationManager.emptyString;
+ informationPopup.icon = good ? StandardIcon.Information : StandardIcon.Critical;
+ informationPopup.text = good ? qsTr("Good signature on ") + results[2] + qsTr(" total and ") + results[3] + qsTr(" spent.") : qsTr("Bad signature");
}
else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
diff --git a/pages/TxKey.qml b/pages/TxKey.qml
index 33b09bb6..e9d6abc8 100644
--- a/pages/TxKey.qml
+++ b/pages/TxKey.qml
@@ -60,13 +60,13 @@ Rectangle {
MoneroComponents.Label {
id: soloTitleLabel
fontSize: 24
- text: qsTr("Prove Transaction") + translationManager.emptyString
+ text: qsTr("Prove Transaction / Reserve") + translationManager.emptyString
}
MoneroComponents.TextPlain {
Layout.fillWidth: true
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
+ "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. \nFor reserve proofs you don't need to specify tx id or address.") + translationManager.emptyString
wrapMode: Text.Wrap
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
@@ -83,6 +83,7 @@ Rectangle {
placeholderText: qsTr("Paste tx ID") + translationManager.emptyString
readOnly: false
copyButton: true
+ enabled: getReserveProofAmtLine.text.length === 0
}
MoneroComponents.LineEdit {
@@ -95,6 +96,38 @@ Rectangle {
placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString;
readOnly: false
copyButton: true
+ enabled: getReserveProofAmtLine.text.length === 0
+ }
+
+ MoneroComponents.LineEdit {
+ id: getReserveProofAmtLine
+ Layout.fillWidth: true
+ labelFontSize: 14
+ labelText: qsTr("Amount") + translationManager.emptyString
+ fontSize: 16
+ placeholderFontSize: 16
+ placeholderText: qsTr("Paste amount of XMR (reserve proof only)") + translationManager.emptyString
+ readOnly: false
+ copyButton: true
+ enabled: getProofAddressLine.text.length === 0 && getProofTxIdLine.text.length === 0
+ onTextChanged: {
+ text = text.trim().replace(",", ".");
+ const match = text.match(/^0+(\d.*)/);
+ if (match) {
+ const cursorPosition = cursorPosition;
+ text = match[1];
+ cursorPosition = Math.max(cursorPosition, 1) - 1;
+ } else if(text.indexOf('.') === 0) {
+ text = '0' + text;
+ if (text.length > 2) {
+ cursorPosition = 1;
+ }
+ }
+ error = walletManager.amountFromString(text) > appWindow.getUnlockedBalance();
+ }
+ validator: RegExpValidator {
+ regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
+ }
}
MoneroComponents.LineEdit {
@@ -113,10 +146,10 @@ Rectangle {
Layout.topMargin: 16
small: true
text: qsTr("Generate") + translationManager.emptyString
- enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype))
+ enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype)) || getReserveProofAmtLine.text.length != 0 && walletManager.amountFromString(getReserveProofAmtLine.text) < appWindow.getUnlockedBalance() && walletManager.amountFromString(getReserveProofAmtLine.text) > 0
onClicked: {
console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text);
- middlePanel.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
+ middlePanel.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text, getReserveProofAmtLine.text)
}
}
@@ -133,12 +166,12 @@ Rectangle {
MoneroComponents.Label {
id: soloTitleLabel2
fontSize: 24
- text: qsTr("Check Transaction") + translationManager.emptyString
+ text: qsTr("Check Transaction / Reserve") + translationManager.emptyString
}
MoneroComponents.TextPlain {
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
+ "For the case with Spend Proof, you don't need to specify the recipient address.\nTransaction is not needed for reserve proof.") + translationManager.emptyString
wrapMode: Text.Wrap
Layout.fillWidth: true
font.family: MoneroComponents.Style.fontRegular.name
@@ -189,7 +222,7 @@ Rectangle {
labelFontSize: 14
labelText: qsTr("Signature") + translationManager.emptyString
placeholderFontSize: 16
- placeholderText: qsTr("Paste tx proof") + translationManager.emptyString;
+ placeholderText: qsTr("Paste tx / reserve proof") + translationManager.emptyString;
readOnly: false
copyButton: true
}
@@ -198,7 +231,7 @@ Rectangle {
Layout.topMargin: 16
small: true
text: qsTr("Check") + translationManager.emptyString
- enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype)))
+ enabled: (TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype)))) || (TxUtils.checkSignature(checkProofSignatureLine.text) && checkProofSignatureLine.text.indexOf("ReserveProofV") === 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype))
onClicked: {
console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text);
middlePanel.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
@@ -222,7 +255,7 @@ Rectangle {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: MoneroComponents.Style.defaultFontColor
- }
+ }
}
}
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index e19a810c..6c22c91a 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -844,6 +844,25 @@ Q_INVOKABLE QString Wallet::checkSpendProof(const QString &txid, const QString &
return QString::fromStdString(result);
}
+Q_INVOKABLE QString Wallet::getReserveProof(bool all, quint32 account_index, quint64 amount, const QString &message) const
+{
+ qDebug("Generating reserve proof");
+ std::string result = m_walletImpl->getReserveProof(all, account_index, amount, message.toStdString());
+ if (result.empty())
+ result = "error|" + m_walletImpl->errorString();
+ return QString::fromStdString(result);
+}
+
+Q_INVOKABLE QString Wallet::checkReserveProof(const QString &address, const QString &message, const QString &signature) const
+{
+ bool good;
+ u_int64_t total;
+ u_int64_t spent;
+ bool success = m_walletImpl->checkReserveProof(address.toStdString(), message.toStdString(), signature.toStdString(), good, total, spent);
+ std::string result = std::string(success ? "true" : "false") + "|" + std::string(good ? "true" : "false") + "|" + QString::number(total).toStdString() + "|" + QString::number(spent).toStdString();
+ 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 9b5bdd46..a81b4555 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -318,6 +318,8 @@ public:
Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const;
Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback);
Q_INVOKABLE QString checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
+ Q_INVOKABLE QString getReserveProof(bool all, quint32 account_index, quint64 amount, const QString &message) const;
+ Q_INVOKABLE QString checkReserveProof(const QString &address, const QString &message, const QString &signature) const;
// Rescan spent outputs
Q_INVOKABLE bool rescanSpent();