changeset 26981:0e8baed80dc3

Save watch only key timestamps when reimporting keys Previously if an existing watch only key was reimported with a new timestamp, the new timestamp would not be saved in the key metadata, and would not be used to update the wallet nTimeFirstKey value (which could cause rescanning to start at the wrong point and miss transactions). Issue was pointed out by Jonas Schnelli <dev@jonasschnelli.ch> in https://github.com/bitcoin/bitcoin/pull/9108#issuecomment-279715550
author Russell Yanofsky <russ@yanofsky.org>
date Tue, 21 Feb 2017 10:53:07 -0500
parents c4e64517a0b7
children 9d8c73415792
files qa/rpc-tests/importmulti.py src/wallet/rpcdump.cpp
diffstat 2 files changed, 24 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/qa/rpc-tests/importmulti.py	Fri Mar 03 17:22:36 2017 +0100
+++ b/qa/rpc-tests/importmulti.py	Tue Feb 21 10:53:07 2017 -0500
@@ -314,6 +314,7 @@
         self.nodes[1].generate(100)
         transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
         self.nodes[1].generate(1)
+        timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
         transaction = self.nodes[1].gettransaction(transactionid)
 
         print("Should import a p2sh with respective redeem script and private keys")
@@ -409,6 +410,24 @@
         assert_equal(address_assert['ismine'], False)
         assert_equal('timestamp' in address_assert, False)
 
+
+        # Importing existing watch only address with new timestamp should replace saved timestamp.
+        assert_greater_than(timestamp, watchonly_timestamp)
+        print("Should replace previously saved watch only timestamp.")
+        result = self.nodes[1].importmulti([{
+            "scriptPubKey": {
+                "address": watchonly_address,
+            },
+            "timestamp": "now",
+        }])
+        assert_equal(result[0]['success'], True)
+        address_assert = self.nodes[1].validateaddress(watchonly_address)
+        assert_equal(address_assert['iswatchonly'], True)
+        assert_equal(address_assert['ismine'], False)
+        assert_equal(address_assert['timestamp'], timestamp)
+        watchonly_timestamp = timestamp
+
+
         # restart nodes to check for proper serialization/deserialization of watch only address
         stop_nodes(self.nodes)
         self.nodes = start_nodes(2, self.options.tmpdir)
--- a/src/wallet/rpcdump.cpp	Fri Mar 03 17:22:36 2017 +0100
+++ b/src/wallet/rpcdump.cpp	Tue Feb 21 10:53:07 2017 -0500
@@ -745,7 +745,7 @@
 
             pwallet->MarkDirty();
 
-            if (!pwallet->HaveWatchOnly(redeemScript) && !pwallet->AddWatchOnly(redeemScript, timestamp)) {
+            if (!pwallet->AddWatchOnly(redeemScript, timestamp)) {
                 throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
             }
 
@@ -762,7 +762,7 @@
 
             pwallet->MarkDirty();
 
-            if (!pwallet->HaveWatchOnly(redeemDestination) && !pwallet->AddWatchOnly(redeemDestination, timestamp)) {
+            if (!pwallet->AddWatchOnly(redeemDestination, timestamp)) {
                 throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
             }
 
@@ -855,7 +855,7 @@
 
                 pwallet->MarkDirty();
 
-                if (!pwallet->HaveWatchOnly(pubKeyScript) && !pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
+                if (!pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
                     throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
                 }
 
@@ -873,7 +873,7 @@
 
                 pwallet->MarkDirty();
 
-                if (!pwallet->HaveWatchOnly(scriptRawPubKey) && !pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
+                if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
                     throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
                 }
 
@@ -947,7 +947,7 @@
 
                 pwallet->MarkDirty();
 
-                if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, timestamp)) {
+                if (!pwallet->AddWatchOnly(script, timestamp)) {
                     throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
                 }