From c6107d8376244560068184cbfafd38d3b2f536b8 Mon Sep 17 00:00:00 2001
From: mmbyday <mmbyday@protonmail.com>
Date: Fri, 14 Dec 2018 17:28:07 -0800
Subject: [PATCH] wizard: allow calendar date for restoration height

---
 js/Wizard.js                    | 43 +++++++++++++++++++++++++++++++++
 wizard/WizardRestoreWallet1.qml | 33 ++++++++++++++++++++-----
 2 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/js/Wizard.js b/js/Wizard.js
index ccef1ba6..6f0633c7 100644
--- a/js/Wizard.js
+++ b/js/Wizard.js
@@ -177,3 +177,46 @@ function restoreWalletCheckViewSpendAddress(walletmanager, nettype, viewkey, spe
 
     return addressOK && viewKeyOK && spendKeyOK
 }
+
+//usage: getApproximateBlockchainHeight("March 18 2016") or getApproximateBlockchainHeight("2016-11-11")
+//returns estimated block height with 1 month buffer prior to requested date.
+function getApproximateBlockchainHeight(_date){
+    // time of monero birth 2014-04-18 10:49:53 (1397818193)
+    var moneroBirthTime = 1397818193;
+    // avg seconds per block in v1
+    var secondsPerBlockV1 = 60;
+    // time of v2 fork 2016-03-23 15:57:38 (1458748658)
+    var forkTime = 1458748658;
+    // v2 fork block
+    var forkBlock = 1009827;
+    // avg seconds per block in V2
+    var secondsPerBlockV2 = 120;
+    // time in UTC
+    var requestedTime = Math.floor(new Date(_date) / 1000);
+    var approxBlockchainHeight;
+    var secondsPerBlock;
+    // before monero's birth
+    if (requestedTime < moneroBirthTime){
+        console.log("Calculated blockchain height: 0, requestedTime < moneroBirthTime " );
+        return 0;
+    }
+    // time between during v1
+    if (requestedTime > moneroBirthTime && requestedTime < forkTime){
+        approxBlockchainHeight = Math.floor((requestedTime - moneroBirthTime)/secondsPerBlockV1);
+        console.log("Calculated blockchain height: " + approxBlockchainHeight );
+        secondsPerBlock = secondsPerBlockV1;
+    }
+    // time is during V2
+    else{
+        approxBlockchainHeight =  Math.floor(forkBlock + (requestedTime - forkTime)/secondsPerBlockV2);
+        console.log("Calculated blockchain height: " + approxBlockchainHeight );
+        secondsPerBlock = secondsPerBlockV2;
+    }
+    var blocksPerMonth = 60*60*24*30/secondsPerBlock;
+    if(approxBlockchainHeight - blocksPerMonth > 0){
+        return approxBlockchainHeight - blocksPerMonth;
+    }
+    else{
+        return 0;
+    }
+}
\ No newline at end of file
diff --git a/wizard/WizardRestoreWallet1.qml b/wizard/WizardRestoreWallet1.qml
index cab4a03e..8b426969 100644
--- a/wizard/WizardRestoreWallet1.qml
+++ b/wizard/WizardRestoreWallet1.qml
@@ -40,11 +40,16 @@ Rectangle {
     property string viewName: "wizardCreateWallet1"
 
     function verify() {
+        if (restoreHeight.text.indexOf('-') === 4 && restoreHeight.text.length !== 10) {
+            return false;
+        }
+
+        var valid = false;
         if(wizardController.walletRestoreMode === "keys") {
-            var valid = wizardRestoreWallet1.verifyFromKeys();
+            valid = wizardRestoreWallet1.verifyFromKeys();
             return valid;
         } else if(wizardController.walletRestoreMode === "seed") {
-            var valid = wizardWalletInput.verify();
+            valid = wizardWalletInput.verify();
             if(!valid) return false;
             valid = Wizard.checkSeed(seedInput.text);
             return valid;
@@ -74,6 +79,10 @@ Rectangle {
             addressLineLength != 0 && viewKeyLineLength != 0 && spendKeyLineLength != 0)
     }
 
+    function checkRestoreHeight() {
+        return (parseInt(restoreHeight) >= 0 || restoreHeight === "") && restoreHeight.indexOf("-") === -1;
+    }
+
     ColumnLayout {
         Layout.alignment: Qt.AlignHCenter;
         width: parent.width - 100
@@ -233,11 +242,13 @@ Rectangle {
                 MoneroComponents.LineEdit {
                     id: restoreHeight
                     Layout.fillWidth: true
-                    labelText: qsTr("Restore height") + translationManager.emptyString
+                    labelText: qsTr("Wallet creation date as `YYYY-MM-DD` or restore height") + translationManager.emptyString
                     labelFontSize: 14 * scaleRatio
                     placeholderFontSize: 16 * scaleRatio
                     placeholderText: qsTr("Restore height") + translationManager.emptyString
-                    validator: RegExpValidator { regExp: /(\d+)?$/ }
+                    validator: RegExpValidator {
+                        regExp: /^(\d+|\d{4}-\d{2}-\d{2})$/
+                    }
                     text: "0"
                 }
 
@@ -263,8 +274,18 @@ Rectangle {
                     wizardController.walletOptionsName = wizardWalletInput.walletName.text;
                     wizardController.walletOptionsLocation = wizardWalletInput.walletLocation.text;
                     wizardController.walletOptionsSeed = seedInput.text;
-                    if(restoreHeight.text)
-                        wizardController.walletOptionsRestoreHeight = parseInt(restoreHeight.text);
+
+                    var _restoreHeight = 0;
+                    if(restoreHeight.text){
+                        // Parse date string or restore height as integer
+                        if(restoreHeight.text.indexOf('-') === 4 && restoreHeight.text.length === 10){
+                            _restoreHeight = Wizard.getApproximateBlockchainHeight(restoreHeight.text);
+                        } else {
+                            _restoreHeight = parseInt(restoreHeight.text)
+                        }
+
+                        wizardController.walletOptionsRestoreHeight = _restoreHeight;
+                    }
 
                     wizardStateView.state = "wizardRestoreWallet2";
                 }