mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-11 14:38:29 +01:00
Use importmulti timestamp when importing watch only keys
When importing a watch-only address over importmulti with a specific timestamp, the wallet's nTimeFirstKey is currently set to 1. After this change, the provided timestamp will be used and stored as metadata associated with watch-only key. This can improve wallet performance because it can avoid the need to scan the entire blockchain for watch only addresses when timestamps are provided. Also adds timestamp to validateaddress return value (needed for tests). Fixes #9034.
This commit is contained in:
@@ -20,6 +20,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
print ("Mining blocks...")
|
||||
self.nodes[0].generate(1)
|
||||
self.nodes[1].generate(1)
|
||||
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
||||
|
||||
# keyword definition
|
||||
PRIV_KEY = 'privkey'
|
||||
@@ -59,6 +60,9 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
watchonly_address = address['address']
|
||||
watchonly_timestamp = timestamp
|
||||
|
||||
|
||||
# ScriptPubKey + internal
|
||||
@@ -73,6 +77,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
|
||||
# ScriptPubKey + !internal
|
||||
print("Should not import a scriptPubKey without internal flag")
|
||||
@@ -87,6 +92,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
|
||||
# Address + Public key + !Internal
|
||||
@@ -103,6 +109,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
|
||||
|
||||
# ScriptPubKey + Public key + internal
|
||||
@@ -119,6 +126,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
|
||||
# ScriptPubKey + Public key + !internal
|
||||
print("Should not import a scriptPubKey without internal and with public key")
|
||||
@@ -135,11 +143,11 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
# Address + Private key + !watchonly
|
||||
print("Should import an address with private key")
|
||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
|
||||
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": address['address']
|
||||
@@ -170,6 +178,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
# ScriptPubKey + Private key + internal
|
||||
print("Should import a scriptPubKey with internal and with private key")
|
||||
@@ -184,6 +193,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], True)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
|
||||
# ScriptPubKey + Private key + !internal
|
||||
print("Should not import a scriptPubKey without internal and with private key")
|
||||
@@ -199,6 +209,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
|
||||
# P2SH address
|
||||
@@ -209,6 +220,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
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")
|
||||
@@ -222,6 +234,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(multi_sig_script['address'])
|
||||
assert_equal(address_assert['isscript'], True)
|
||||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
|
||||
assert_equal(p2shunspent['spendable'], False)
|
||||
assert_equal(p2shunspent['solvable'], False)
|
||||
@@ -235,6 +248,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
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")
|
||||
@@ -246,6 +260,8 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
"redeemscript": multi_sig_script['redeemScript']
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].validateaddress(multi_sig_script['address'])
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
|
||||
p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
|
||||
assert_equal(p2shunspent['spendable'], False)
|
||||
@@ -260,6 +276,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
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")
|
||||
@@ -272,6 +289,8 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
"keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])]
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].validateaddress(multi_sig_script['address'])
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
|
||||
p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0]
|
||||
assert_equal(p2shunspent['spendable'], False)
|
||||
@@ -319,6 +338,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
|
||||
# ScriptPubKey + Public key + internal + Wrong pubkey
|
||||
@@ -338,6 +358,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
|
||||
# Address + Private key + !watchonly + Wrong private key
|
||||
@@ -357,6 +378,7 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
|
||||
# ScriptPubKey + Private key + internal + Wrong private key
|
||||
@@ -375,6 +397,15 @@ class ImportMultiTest (BitcoinTestFramework):
|
||||
address_assert = self.nodes[1].validateaddress(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
# restart nodes to check for proper serialization/deserialization of watch only address
|
||||
stop_nodes(self.nodes)
|
||||
self.nodes = start_nodes(2, self.options.tmpdir)
|
||||
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'], watchonly_timestamp);
|
||||
|
||||
# Bad or missing timestamps
|
||||
print("Should throw on invalid or missing timestamp values")
|
||||
|
||||
Reference in New Issue
Block a user