mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-05-05 11:28:49 +02:00
[Wallet] split the keypool in an internal and external part
This commit is contained in:
@@ -467,6 +467,8 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
# drain the keypool
|
||||
self.nodes[1].getnewaddress()
|
||||
self.nodes[1].getrawchangeaddress()
|
||||
self.nodes[1].getrawchangeaddress()
|
||||
inputs = []
|
||||
outputs = {self.nodes[0].getnewaddress():1.1}
|
||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
@@ -476,6 +478,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
#refill the keypool
|
||||
self.nodes[1].walletpassphrase("test", 100)
|
||||
self.nodes[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
|
||||
self.nodes[1].walletlock()
|
||||
|
||||
assert_raises_jsonrpc(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 1.2)
|
||||
|
||||
@@ -27,28 +27,38 @@ class KeyPoolTest(BitcoinTestFramework):
|
||||
wallet_info = nodes[0].getwalletinfo()
|
||||
assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid'])
|
||||
assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid'])
|
||||
|
||||
assert_raises_jsonrpc(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)
|
||||
|
||||
# put three new keys in the keypool
|
||||
# put six (plus 2) new keys in the keypool (100% external-, +20% internal-keys, 2 in min)
|
||||
nodes[0].walletpassphrase('test', 12000)
|
||||
nodes[0].keypoolrefill(3)
|
||||
nodes[0].keypoolrefill(6)
|
||||
nodes[0].walletlock()
|
||||
wi = nodes[0].getwalletinfo()
|
||||
assert_equal(wi['keypoolsize_hd_internal'], 2)
|
||||
assert_equal(wi['keypoolsize'], 6)
|
||||
|
||||
# drain the keys
|
||||
# drain the internal keys
|
||||
nodes[0].getrawchangeaddress()
|
||||
nodes[0].getrawchangeaddress()
|
||||
addr = set()
|
||||
addr.add(nodes[0].getrawchangeaddress())
|
||||
addr.add(nodes[0].getrawchangeaddress())
|
||||
addr.add(nodes[0].getrawchangeaddress())
|
||||
addr.add(nodes[0].getrawchangeaddress())
|
||||
# assert that four unique addresses were returned
|
||||
assert(len(addr) == 4)
|
||||
# the next one should fail
|
||||
assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].getrawchangeaddress)
|
||||
|
||||
# drain the external keys
|
||||
addr.add(nodes[0].getnewaddress())
|
||||
addr.add(nodes[0].getnewaddress())
|
||||
addr.add(nodes[0].getnewaddress())
|
||||
addr.add(nodes[0].getnewaddress())
|
||||
addr.add(nodes[0].getnewaddress())
|
||||
addr.add(nodes[0].getnewaddress())
|
||||
assert(len(addr) == 6)
|
||||
# the next one should fail
|
||||
assert_raises_jsonrpc(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)
|
||||
|
||||
# refill keypool with three new addresses
|
||||
nodes[0].walletpassphrase('test', 1)
|
||||
nodes[0].keypoolrefill(3)
|
||||
|
||||
# test walletpassphrase timeout
|
||||
time.sleep(1.1)
|
||||
assert_equal(nodes[0].getwalletinfo()["unlocked_until"], 0)
|
||||
@@ -57,9 +67,14 @@ class KeyPoolTest(BitcoinTestFramework):
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].generate, 1)
|
||||
|
||||
nodes[0].walletpassphrase('test', 100)
|
||||
nodes[0].keypoolrefill(100)
|
||||
wi = nodes[0].getwalletinfo()
|
||||
assert_equal(wi['keypoolsize_hd_internal'], 20)
|
||||
assert_equal(wi['keypoolsize'], 100)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = False
|
||||
|
||||
@@ -88,7 +88,7 @@ class WalletDumpTest(BitcoinTestFramework):
|
||||
read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, None)
|
||||
assert_equal(found_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_addr_chg, 50) # 50 blocks where mined
|
||||
assert_equal(found_addr_rsv, 90 + 1) # keypool size (TODO: fix off-by-one)
|
||||
assert_equal(found_addr_rsv, 90*1.2) # 90 keys plus 20% internal keys
|
||||
|
||||
#encrypt wallet, restart, unlock and dump
|
||||
self.nodes[0].encryptwallet('test')
|
||||
@@ -102,8 +102,8 @@ class WalletDumpTest(BitcoinTestFramework):
|
||||
found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_enc = \
|
||||
read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, hd_master_addr_unenc)
|
||||
assert_equal(found_addr, test_addr_count)
|
||||
assert_equal(found_addr_chg, 90 + 1 + 50) # old reserve keys are marked as change now
|
||||
assert_equal(found_addr_rsv, 90 + 1) # keypool size (TODO: fix off-by-one)
|
||||
assert_equal(found_addr_chg, 90*1.2 + 50) # old reserve keys are marked as change now
|
||||
assert_equal(found_addr_rsv, 90*1.2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletDumpTest().main ()
|
||||
|
||||
@@ -42,6 +42,11 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
|
||||
assert_equal(len(masterkeyid), 40)
|
||||
|
||||
#create an internal key
|
||||
change_addr = self.nodes[1].getrawchangeaddress()
|
||||
change_addrV= self.nodes[1].validateaddress(change_addr);
|
||||
assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key
|
||||
|
||||
# Import a non-HD private key in the HD wallet
|
||||
non_hd_add = self.nodes[0].getnewaddress()
|
||||
self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))
|
||||
@@ -65,6 +70,11 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
self.nodes[0].sendtoaddress(non_hd_add, 1)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
#create an internal key (again)
|
||||
change_addr = self.nodes[1].getrawchangeaddress()
|
||||
change_addrV= self.nodes[1].validateaddress(change_addr);
|
||||
assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key
|
||||
|
||||
self.sync_all()
|
||||
assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
|
||||
|
||||
@@ -90,6 +100,15 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
#connect_nodes_bi(self.nodes, 0, 1)
|
||||
assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
|
||||
|
||||
#send a tx and make sure its using the internal chain for the changeoutput
|
||||
txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||
outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout'];
|
||||
keypath = ""
|
||||
for out in outs:
|
||||
if out['value'] != 1:
|
||||
keypath = self.nodes[1].validateaddress(out['scriptPubKey']['addresses'][0])['hdkeypath']
|
||||
|
||||
assert(keypath[0:7] == "m/0'/1'")
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletHDTest().main ()
|
||||
|
||||
Reference in New Issue
Block a user