tcreated rescan script to take advantage of the new rescanblockchain rpc call - electrum-personal-server - Maximally lightweight electrum server for a single user
git clone https://git.parazyd.org/electrum-personal-server
Log
Files
Refs
README
---
commit 314443ac47f77ce90490744ecef5071581ffe2c1
parent ee671a20350e72a1210f4ad6530677ef563cf2d4
Author: chris-belcher 
Date:   Sat,  3 Mar 2018 19:21:17 +0000

created rescan script to take advantage of the new rescanblockchain rpc call

Diffstat:
  A rescan-script.bat                   |       4 ++++
  A rescan-script.py                    |      63 +++++++++++++++++++++++++++++++
  M server.py                           |       6 +++---

3 files changed, 70 insertions(+), 3 deletions(-)
---
diff --git a/rescan-script.bat b/rescan-script.bat
t@@ -0,0 +1,3 @@
+@echo off
+python3 rescan-script.py
+pause
+\ No newline at end of file
diff --git a/rescan-script.py b/rescan-script.py
t@@ -0,0 +1,63 @@
+#! /usr/bin/python3
+
+from configparser import ConfigParser, NoSectionError
+from jsonrpc import JsonRpc, JsonRpcError
+from datetime import datetime
+
+def search_for_block_height_of_date(datestr, rpc):
+    target_time = datetime.strptime(datestr, "%d/%m/%Y")
+    bestblockhash = rpc.call("getbestblockhash", [])
+    best_head = rpc.call("getblockheader", [bestblockhash])
+    if target_time > datetime.fromtimestamp(best_head["time"]):
+        print("ERROR: date in the future")
+        return -1
+    genesis_block = rpc.call("getblockheader", [rpc.call("getblockhash", [0])])
+    if target_time < datetime.fromtimestamp(genesis_block["time"]):
+        print("WARNING: date is before the creation of bitcoin")
+        return 0
+    first_height = 0
+    last_height = best_head["height"]
+    while True:
+        m = (first_height + last_height) // 2
+        m_header = rpc.call("getblockheader", [rpc.call("getblockhash", [m])])
+        m_header_time = datetime.fromtimestamp(m_header["time"])
+        m_time_diff = (m_header_time - target_time).total_seconds()
+        if abs(m_time_diff) < 60*60*2: #2 hours
+            return m_header["height"]
+        elif m_time_diff < 0:
+            first_height = m
+        elif m_time_diff > 0:
+            last_height = m
+        else:
+            return -1
+
+def main():
+    try:
+        config = ConfigParser()
+        config.read(["config.cfg"])
+        config.options("electrum-master-public-keys")
+    except NoSectionError:
+        log("Non-existant configuration file `config.cfg`")
+        return
+    rpc = JsonRpc(host = config.get("bitcoin-rpc", "host"),
+                port = int(config.get("bitcoin-rpc", "port")),
+                user = config.get("bitcoin-rpc", "user"),
+                password = config.get("bitcoin-rpc", "password"))
+    user_input = input("Enter earliest wallet creation date (DD/MM/YYYY) "
+        "or block height to rescan from: ")
+    try:
+        height = int(user_input)
+    except ValueError:
+        height = search_for_block_height_of_date(user_input, rpc)
+        if height == -1:
+            return
+        height -= 2016 #go back two weeks for safety
+
+    if input("Rescan from block height " + str(height) + " ? (y/n):") != 'y':
+        return
+    rpc.call("rescanblockchain", [height])
+    print("end")
+    
+
+main()
+
diff --git a/server.py b/server.py
t@@ -672,10 +672,10 @@ def main():
         get_scriptpubkeys_to_monitor(rpc, config)
     if import_needed:
         import_addresses(rpc, relevant_spks_addrs)
-        #TODO tell people about the rescanblockchain call which allows a range
         log("Done.\nIf recovering a wallet which already has existing " +
-            "transactions, then\nrestart Bitcoin with -rescan. If your " +
-            "wallet is new and empty then just restart this script")
+            "transactions, then\nrun the rescan script. If you're confident " +
+            "that the wallets are new\nand empty then there's no need to " +
+            "rescan, just restart this script")
     else:
         address_history, unconfirmed_txes = build_address_history(
             rpc, relevant_spks_addrs, deterministic_wallets)