|
|
|
@ -170,5 +170,101 @@ class WalletHDTest(BitcoinTestFramework):
|
|
|
|
|
assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed)
|
|
|
|
|
assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
|
|
|
|
|
|
|
|
|
|
self.log.info('Test sethdseed restoring with keys outside of the initial keypool')
|
|
|
|
|
self.nodes[0].generate(10)
|
|
|
|
|
# Restart node 1 with keypool of 3 and a different wallet
|
|
|
|
|
self.nodes[1].createwallet(wallet_name='origin', blank=True)
|
|
|
|
|
self.stop_node(1)
|
|
|
|
|
self.start_node(1, extra_args=['-keypool=3', '-wallet=origin'])
|
|
|
|
|
connect_nodes(self.nodes[0], 1)
|
|
|
|
|
|
|
|
|
|
# sethdseed restoring and seeing txs to addresses out of the keypool
|
|
|
|
|
origin_rpc = self.nodes[1].get_wallet_rpc('origin')
|
|
|
|
|
seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
|
|
|
|
|
origin_rpc.sethdseed(True, seed)
|
|
|
|
|
|
|
|
|
|
self.nodes[1].createwallet(wallet_name='restore', blank=True)
|
|
|
|
|
restore_rpc = self.nodes[1].get_wallet_rpc('restore')
|
|
|
|
|
restore_rpc.sethdseed(True, seed) # Set to be the same seed as origin_rpc
|
|
|
|
|
restore_rpc.sethdseed(True) # Rotate to a new seed, making original `seed` inactive
|
|
|
|
|
|
|
|
|
|
self.nodes[1].createwallet(wallet_name='restore2', blank=True)
|
|
|
|
|
restore2_rpc = self.nodes[1].get_wallet_rpc('restore2')
|
|
|
|
|
restore2_rpc.sethdseed(True, seed) # Set to be the same seed as origin_rpc
|
|
|
|
|
restore2_rpc.sethdseed(True) # Rotate to a new seed, making original `seed` inactive
|
|
|
|
|
|
|
|
|
|
# Check persistence of inactive seed by reloading restore. restore2 is still loaded to test the case where the wallet is not reloaded
|
|
|
|
|
restore_rpc.unloadwallet()
|
|
|
|
|
self.nodes[1].loadwallet('restore')
|
|
|
|
|
restore_rpc = self.nodes[1].get_wallet_rpc('restore')
|
|
|
|
|
|
|
|
|
|
# Empty origin keypool and get an address that is beyond the initial keypool
|
|
|
|
|
origin_rpc.getnewaddress()
|
|
|
|
|
origin_rpc.getnewaddress()
|
|
|
|
|
last_addr = origin_rpc.getnewaddress() # Last address of initial keypool
|
|
|
|
|
addr = origin_rpc.getnewaddress() # First address beyond initial keypool
|
|
|
|
|
|
|
|
|
|
# Check that the restored seed has last_addr but does not have addr
|
|
|
|
|
info = restore_rpc.getaddressinfo(last_addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
info = restore_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], False)
|
|
|
|
|
info = restore2_rpc.getaddressinfo(last_addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
info = restore2_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], False)
|
|
|
|
|
# Check that the origin seed has addr
|
|
|
|
|
info = origin_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
|
|
|
|
|
# Send a transaction to addr, which is out of the initial keypool.
|
|
|
|
|
# The wallet that has set a new seed (restore_rpc) should not detect this transaction.
|
|
|
|
|
txid = self.nodes[0].sendtoaddress(addr, 1)
|
|
|
|
|
origin_rpc.sendrawtransaction(self.nodes[0].gettransaction(txid)['hex'])
|
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
|
origin_rpc.gettransaction(txid)
|
|
|
|
|
assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', restore_rpc.gettransaction, txid)
|
|
|
|
|
out_of_kp_txid = txid
|
|
|
|
|
|
|
|
|
|
# Send a transaction to last_addr, which is in the initial keypool.
|
|
|
|
|
# The wallet that has set a new seed (restore_rpc) should detect this transaction and generate 3 new keys from the initial seed.
|
|
|
|
|
# The previous transaction (out_of_kp_txid) should still not be detected as a rescan is required.
|
|
|
|
|
txid = self.nodes[0].sendtoaddress(last_addr, 1)
|
|
|
|
|
origin_rpc.sendrawtransaction(self.nodes[0].gettransaction(txid)['hex'])
|
|
|
|
|
self.nodes[0].generate(1)
|
|
|
|
|
origin_rpc.gettransaction(txid)
|
|
|
|
|
restore_rpc.gettransaction(txid)
|
|
|
|
|
assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', restore_rpc.gettransaction, out_of_kp_txid)
|
|
|
|
|
restore2_rpc.gettransaction(txid)
|
|
|
|
|
assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', restore2_rpc.gettransaction, out_of_kp_txid)
|
|
|
|
|
|
|
|
|
|
# After rescanning, restore_rpc should now see out_of_kp_txid and generate an additional key.
|
|
|
|
|
# addr should now be part of restore_rpc and be ismine
|
|
|
|
|
restore_rpc.rescanblockchain()
|
|
|
|
|
restore_rpc.gettransaction(out_of_kp_txid)
|
|
|
|
|
info = restore_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
restore2_rpc.rescanblockchain()
|
|
|
|
|
restore2_rpc.gettransaction(out_of_kp_txid)
|
|
|
|
|
info = restore2_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
|
|
|
|
|
# Check again that 3 keys were derived.
|
|
|
|
|
# Empty keypool and get an address that is beyond the initial keypool
|
|
|
|
|
origin_rpc.getnewaddress()
|
|
|
|
|
origin_rpc.getnewaddress()
|
|
|
|
|
last_addr = origin_rpc.getnewaddress()
|
|
|
|
|
addr = origin_rpc.getnewaddress()
|
|
|
|
|
|
|
|
|
|
# Check that the restored seed has last_addr but does not have addr
|
|
|
|
|
info = restore_rpc.getaddressinfo(last_addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
info = restore_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], False)
|
|
|
|
|
info = restore2_rpc.getaddressinfo(last_addr)
|
|
|
|
|
assert_equal(info['ismine'], True)
|
|
|
|
|
info = restore2_rpc.getaddressinfo(addr)
|
|
|
|
|
assert_equal(info['ismine'], False)
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
WalletHDTest().main ()
|
|
|
|
|